Get current iTunesStore country - iphone

I need to get currently activated iTunes store country code. I have read about getting current locale, but this is not very smart solution, since user can have one locale but totally different iTunes account. The solution does not need to be legal, apple rejection is not a problem here. Does anybody have found solution for this scenario using private frameworks?

You can do this after you've requested the store's products by checking the NSLocale on one of the product's priceLocale. Try this code:
- (NSString*) storeCountryCode:(NSArray*) products
{
NSString* countryCode = nil;
SKProduct* product = [products objectAtIndex:0];
if(product != nil)
{
NSLocale* storeLocale = product.priceLocale;
countryCode = (__bridge NSString*)CFLocaleGetValue((__bridge CFLocaleRef)storeLocale, kCFLocaleCountryCode);
}
return countryCode;
}
You could call this from your SKProductsRequestDelegate method:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSString* storeCountryCode = [self storeCountryCode:response.products];
//other product handling
}

you can "CFLocaleGetValue" call this use
NSString *aCountry=[getCurrentItunesStoreCountryFromProudct:myProudct];
-(NSString *)getCurrentItunesStoreCountryFromProudct:(SKProduct *)aProudct
{
NSLocale* storeLocale = aProudct.priceLocale;
NSString *storeCountry = (NSString*)CFLocaleGetValue((CFLocaleRef)storeLocale, kCFLocaleCountryCode);
return storeCountry;
}

You can obtain the Storefront ID with this code. As it relies on private APIs, do not use in production code.
NSError *error = nil;
BOOL loaded = [[NSBundle bundleWithPath:#"/System/Library/PrivateFrameworks/iTunesStore.framework"] loadAndReturnError:&error];
if (loaded) {
NSString *localStoreFrontID = nil;
#try {
localStoreFrontID = [NSClassFromString(#"ISClient") valueForKeyPath:#"currentClient.localStoreFrontID"];
}
#catch (NSException *exception) {
NSLog(#"%#", exception);
}
NSLog(#"localStoreFrontID: %#", localStoreFrontID);
}
else {
NSLog(#"Error: %#", error);
}
On iOS 5.1.1, this printed localStoreFrontID: 143459-2,2 for me, i.e. the Swiss store. I’m not sure what the -2,2 suffix mean, maybe it is about the language. I have not tested this on iOS 6.
Note that it even works after you sign out of your account in Settings → Store.

Related

how to fix -[__NSCFString gtm_stringByUnescapingFromURLArgument] in google+ authentication

I am trying to create an application that retrieves the current user's email id, user id, user name from his google+ account. The part of the code is as follows,
- (IBAction)googleSigninBtnTapped:(id)sender
{
[GPPSignInButton class];
[GPPSignIn sharedInstance].clientID =[NSString stringWithFormat:#"MY APP ID"];
GPPSignIn *signIn = [GPPSignIn sharedInstance];
signIn.delegate = self;
signIn.shouldFetchGoogleUserEmail = YES;
signIn.shouldFetchGoogleUserID = YES;
signIn.actions = [NSArray arrayWithObjects:
#"http://schemas.google.com/AddActivity",
#"http://schemas.google.com/BuyActivity",
#"http://schemas.google.com/CheckInActivity",
#"http://schemas.google.com/CommentActivity",
#"http://schemas.google.com/CreateActivity",
#"http://schemas.google.com/ListenActivity",
#"http://schemas.google.com/ReserveActivity",
#"http://schemas.google.com/ReviewActivity",
nil];
[signIn trySilentAuthentication];
}
(void)finishedWithAuth:(GTMOAuth2Authentication *)auth error:(NSError )error
{
if (error)
{
NSLog(#"Status: Authentication error: %#", error);
}
else
{
NSLog(#"Status: Authenticated");
NSLog(#"Email: %#",[GPPSignIn sharedInstance].authentication.userEmail);
GTLServicePlus plusService = [[[GTLServicePlus alloc] init] autorelease];
plusService.retryEnabled = YES;
[plusService setAuthorizer:[GPPSignIn sharedInstance].authentication];
GTLQueryPlus *query = [GTLQueryPlus queryForPeopleGetWithUserId:#"me"];
[plusService executeQuery:query completionHandler:^(GTLServiceTicket *ticket, GTLPlusPerson *person, NSError *error)
{
if (error)
{
GTMLoggerError(#"Error: %#", error);
}
else
{
[person retain];
NSLog(#"%#", person.displayName);
NSLog(#"%#", person.identifier);
}
}];
}
}
But when i am trying to execute my app, it gets crashed, saying that
'-[__NSCFString gtm_stringByUnescapingFromURLArgument]: unrecognized selector sent to instance 0x9e435b0'
Can anybody help me on this...!!!
Thanks In Advance!!!
Yep, you need the -ObjC linker flag in, it's not finding one of the categories from the GoogleOpenSource framework.
See Step 3 in the setup guide: https://developers.google.com/+/mobile/ios/getting-started#step_3_initialize_the_google_client
Basically, in Other Linker Flags, add -ObjC (capitalisation is important, note!). Also make sure you have included both GooglePlus and GoogleOpenSource frameworks in your project.
Add with _objc the other flag called -lc++

How to generate unique identifier which should work in all iOS versions?

I want to get the unique identifier which should support all iOS versions..Can any one help me on this issue. As you know that apple is deprecated the UDID method, So there is possibility to generate Unique id using wifi-mac address.But apple is going to remove the wifi mac address in iOS7 version.So my requirement is to generate a new unique code which should work in all iOS versions.Thanks in advance..
Note: Don't change the UDID once user restart the device or reinstall the application.
I was updating my application that was working based only on Unique Identifier which supported iOS 4.3 and above. So,
1) I was unable to use [UIDevice currentDevice].uniqueIdentifier; as it was no longer available
2) I could not use [UIDevice currentDevice].identifierForVendor.UUIDString because it was Available in iOS 6.0 and later only and was unable to use for lower iOS versions.
3) The mac address was not an option as it wasn't allowed in iOS-7
4) OpenUDID was deprecated some time ago and also had issues with iOS-6.
5) Advertisement identifiers were also not available for iOS-5 and below
Finally this was what i did
a) Added SFHFKeychainUtils to the project
b) Generated CFUUID key String
CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);
udidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));
c) Saved it to Key Chain Utils or else it will generate a new Unique Each Time
Final Code
+ (NSString *)GetDeviceID {
NSString *udidString;
udidString = [self objectForKey:#"deviceID"];
if(!udidString)
{
CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);
udidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));
CFRelease(cfuuid);
[self setObject:udidString forKey:#"deviceID"];
}
return udidString;
}
+(void) setObject:(NSString*) object forKey:(NSString*) key
{
NSString *objectString = object;
NSError *error = nil;
[SFHFKeychainUtils storeUsername:key
andPassword:objectString
forServiceName:#"LIB"
updateExisting:YES
error:&error];
if(error)
NSLog(#"%#", [error localizedDescription]);
}
+(NSString*) objectForKey:(NSString*) key
{
NSError *error = nil;
NSString *object = [SFHFKeychainUtils getPasswordForUsername:key
andServiceName:#"LIB"
error:&error];
if(error)
NSLog(#"%#", [error localizedDescription]);
return object;
}
For further Details
Now Device Identifier change to UUID.You can get UUID With the help of following code:
- (NSString *)getUUID
{
NSString *UUID = [[NSUserDefaults standardUserDefaults] objectForKey:#"uniqueID"];
if (!UUID) {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
UUID = [(__bridge NSString*)string stringByReplacingOccurrencesOfString:#"-"withString:#""];
[[NSUserDefaults standardUserDefaults] setValue:UUID forKey:#"uniqueID"];
}
return UUID;
}
It's Work in all iOS version.
I don't have access to the code right now (can post in a few hours if you still need it) but what I've done is create a static method 'deviceIdentifier' in a helper class.
the method does a basic check for the current iOS version, returns UDID if below 6.0 and uniqueIdentifier otherwise
Let me know if you'd like the code for that and I'll post it when I can..it's only 10-15 lines or so if I remember right but makes a big difference as then you can just call '[myHelper deviceIdentifier]' wherever you need a device ID and not have to worry about which iOS version they are using

VerificationController unrecognized selector iOS 5.0.1

I just added In-App Purchasing to my iOS app and a few of my users are crashing out with
-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0xf0a6f10
Obtained from BugSense, the memory location refers to the last line of this excerpt from Apple's VerificationController.m
- (BOOL)isTransactionAndItsReceiptValid:(SKPaymentTransaction *)transaction
{
if (!(transaction && transaction.transactionReceipt && [transaction.transactionReceipt length] > 0))
{
// Transaction is not valid.
return NO;
}
// Pull the purchase-info out of the transaction receipt, decode it, and save it for later so
// it can be cross checked with the verifyReceipt.
NSDictionary *receiptDict = [self dictionaryFromPlistData:transaction.transactionReceipt];
NSString *transactionPurchaseInfo = [receiptDict objectForKey:#"purchase-info"];
...
receiptDict is generated by this code (also included in VerificationController.m)
- (NSDictionary *)dictionaryFromPlistData:(NSData *)data
{
NSError *error;
NSDictionary *dictionaryParsed = [NSPropertyListSerialization propertyListWithData:data
options:NSPropertyListImmutable
format:nil
error:&error];
if (!dictionaryParsed)
{
if (error)
{
#warning Handle the error here.
}
return nil;
}
return dictionaryParsed;
}
which should return an NSDictionary or nil.
ARC is turned on. This problem seems to only occur with iOS 5.0.1 users. While I did make necessary changes to VerificationController.m, this part has been untouched. I can't seem to replicate the problem on my iPad running iOS 5.1.1, but users have said that it is persistent even after reinstalling the app. If anyone can see something simple that I'm not doing right, I'd appreciate it.
EDIT
Follow up question. What does it mean when
- (BOOL)isTransactionAndItsReceiptValid:(SKPaymentTransaction *)transaction
transaction.transactionReceipt
only provides an NSString and is it safe to ignore?
looks like to me
propertyListWithData:data options:NSPropertyListImmutableformat:nil error:&error];
return a string not a dictionary but it doesnt seems logic. are you sure the problem come from this?

GData Picasa Photo Album iPhone

I was hoping someone could help me with this problem. I am trying to access a Picasa Web Album from my iphone application. I have used GData previously with Google Calendar and getting events and the data related to them before, so I set up my methods in a similar fashion. I however am getting an error that is telling me the following
serviceBase:<GDataServiceGooglePhotos: 0x4d4e6d0> objectFetcher:<GDataHTTPFetcher: 0xbaa35c0> failedWithStatus:400 data:Too many results requested
I am think that I have narrowed down the problem that I am having has something to do with the ticket that I am using, in the following line
ticket = [service fetchFeedWithURL:[NSURL URLWithString:kGDataGooglePhotosAllFeed]
delegate:self
didFinishSelector:#selector(photosListTicket:finishedWithFeed:error:)];
I however am unable to get past this problem. Does anyone have a suggestion to get past this problem. Am I doing something wrong?
My full code for the retrieval of the pictures is shown below. Anywhere that says picAlbum, that is a predefined NSArray to hold the information.
- (GDataServiceGooglePhotos *)photoService {
static GDataServiceGooglePhotos* service = nil;
if (!service) {
service = [[GDataServiceGooglePhotos alloc] init];
[service setShouldCacheDatedData:YES];
[service setServiceShouldFollowNextLinks:YES];
}
[service setUserCredentialsWithUsername:#"username"
password:#"password"];
return service;
}
-(void)loadGooglePhotos {
[self fetchAllPhotos];
}
-(void)fetchAllPhotos {
NSLog(#"In fetchAllPhotos");
GDataServiceGooglePhotos *service = [self photoService];
GDataServiceTicket *ticket;
ticket = [service fetchFeedWithURL:[NSURL URLWithString:kGDataGooglePhotosKindAlbum]
delegate:self
didFinishSelector:#selector(photosListTicket:finishedWithFeed:error:)];
}
- (void)photosListTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataFeedPhotoAlbum *)feed error:(NSError *)error {
NSLog(#"In photosListTicket");
NSArray *photos = [feed entries];
if ([photos count] != 0){
self.picAlbum = [photos objectAtIndex:0];
NSLog(#"fetching photos");
[self fetchPhotos];
}
else {
NSLog(#"User has no photos...");
}
}
- (void)fetchPhotos {
NSLog(#"In fetchPhotos");
if (self.picAlbum) {
NSURL *feedURL = [[self.picAlbum alternateLink] URL];
if (feedURL) {
NSLog(feedURL);
GDataQueryGooglePhotos *query = [GDataQueryGooglePhotos photoQueryWithFeedURL:feedURL];
[query setMaxResults:1000];
GDataServiceGooglePhotos *service = [self photoService];
GDataServiceTicket *ticket;
ticket = [service fetchFeedWithQuery:query delegate:self didFinishSelector:#selector(photosEventsTicket:finishedWithFeed:error:)];
}
}
}
- (void)photosEventsTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataFeedPhotoAlbum *)feed error:(NSError *)error {
NSLog(#"In photosEventsTicket");
NSArray *photos = [feed entries];
NSLog([NSString stringWithFormat:#"%i",[photos count]]);
}
Thanks in advance for any information or help that you can provide.
If the server says "Too many results requested" that's a clue that the max results query parameter is too big.
The fetches in the code snippet do not appear functional. Neither kGDataGooglePhotosKindAlbum nor an album's alternateLink would be URLs for feeds.

Problem with custom UIImagePickerController with SDK 4.0

I'm trying to create own UIImagePickerController using Assets Library Framework from the latest SDK 4.0. Here's the code:
-(void)viewDidLoad{
[super viewDidLoad];
groups = [[NSMutableArray alloc] init];
ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
NSUInteger groupTypes = ALAssetsGroupAlbum;
ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
if (group)
[groups addObject:group];
};
ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) {
NSString *errorTitle = [error localizedDescription];
NSString *errorMessage = [error localizedRecoverySuggestion];
NSString *errorFailureDesc = [error localizedFailureReason];
NSLog(#"Error: %#, Suggestion: %#, Failure desc: %#", errorTitle, errorMessage, errorFailureDesc);
};
[assetsLibrary enumerateGroupsWithTypes:groupTypes usingBlock:listGroupBlock failureBlock:failureBlock];
}
The problem here is that I receive an error and the failure block is called from the gorups enumerator. Here's the log:
Error: Global denied access
Suggestion: This setting can be
changed in Preferences.
Failure desc: The user has denied all
applications access to their media.
As shown in the SDK 4.0 demonstrations there should be displayed a message that the application wants access to the photo albums and the user should grand access. I see no message at all and receive the error described above. Is there someone who can tell me what should be changed in the Preferences to solve the problem?
Thanks,
Viktor.
In order to access this information Location Serivices should be tunred ON!!! There is no need to reset all the settings. In this case the allow access dialog will appear.