get or simulate NSLocale for current user - ios

I want my App to be used from few iTunes stores. I read NSLocale Class Reference and they are talking about "current user". So, who is "current user"? Is it user which has downloaded app?
1) is it possible to get NSLocale depending on current appleID country or iTunes store country from which my App was downloaded?
2) is it possible to simulate NSLocale to test my App?

In iOS, there is no such thing as a "current user". The reference to "current user" in the NSLocale docs is probably a hold over from the OS X docs.
In iOS, run the Settings app and go to General, then International. The "Region Format" and the "Language" settings define what you get back in iOS for [NSLocale currentLocale].
There is no way, in iOS, for a third party app to obtain any sort of appleID or information about a specific iTunes store.
To directly answer your two questions:
1) No, you have no access to this information
2) Yes, run the Settings app and change the Language and/or Region Format settings. This will affect the NSLocale you obtain in your app.

Mates, i found a solution to get user's (Apple ID, iTunes store) locale! You can get locale from SKProduct.
if([SKPaymentQueue canMakePayments])
{
[self requestProductData];
}
#pragma mark -
#pragma mark In-App Purchase Delegate Methods
- (void)requestProductData
{
NSLog(#"IN-APP:requestProductData");
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:<your in-app identifier>]];
request.delegate = self;
[request start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *myProduct = [[NSArray alloc]initWithArray:response.products];
if ([myProduct count]>0)
{
SKProduct *product = [myProduct objectAtIndex:0];
NSLog(#"Price: %.2f",product.price.floatValue);
NSLog(#"Price Locale: %#",product.priceLocale.localeIdentifier);
NSLog(#"Product Identifier: %#",product.productIdentifier);
NSLog(#"IN-APP:array count: %i", [myProduct count]);
[request autorelease];
}
[myProduct release];
myProduct = nil;
}

Related

How to test In-app purchase in Sandbox mode iOS?

Am new to In-app purchase integration in iOS application. I have done the coding in the project level and I have created a Sandbox user in iTunes Connect. I read many tutorials and Apple Document to test the In-App purchase in DEV mode.
As per the document I have removed the APPLE ID from iPad Settings and launched the app from Xcode. But, I didn't received the Account Alert from the app. Also, my products are returning empty in SKProductRequest delegate method didReceiveResponse. I have posted my code for your reference. Can you please help me on this? Am working since last two days. Please help me. Thanks in advance.
- (void) getAvailProducts
{
NSLog(#"Fetching Available Products");
NSSet *productIdentifiers = [NSSet setWithObjects:#"com.test.testios.monthly", #"com.test.testios.yearly" ,nil];
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
self.productsRequest.delegate = self;
[self.productsRequest start];
}
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
//SKProduct *validProduct = nil;
DebugLog(#"\n Products: %#", response.products);
NSUInteger count = [response.products count];
NSLog(#"Request Count: %lu", (unsigned long)count);
if (count > 0)
{
self.validatedProducts = response.products;
DebugLog(#“\n Products: %#", response.products);
self.validationCheck = TRUE;
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
// Check subscription
}
else
{
// No products found….
}
}
Also, I tried with "monthly and yearly" instead of "com.test.testios.monthly and com.test.testios.yearly". But, no results.
Edit: Am getting the mentioned ProductIds are invalid in the following code,
for (NSString *invalidProductId in response.invalidProductIdentifiers)
{
NSLog(#"Invalid product id: %#" , invalidProductId);
}
Thank you all.
Fixed the issue and tested the In-App purchase in Sandbox environment. Following items fixed my issue,
1. iTunes Agreement was not accepted.
2. Tax and Payment details was not added.
3. Added correct Product Identifier in project.

Issue with InApp purchase in Sandbox mode: SKProductsRequest delegate returns inconsistent response

When requesting for in-app auto renewable subscription products from apple, I sometimes get valid products but most of the times I get invalidProductIdentifiers in SKProductsResponse object. I wrote a small piece of code to verify this inconsistency in response:
-(void)viewDidAppear:(BOOL)animated{
[self getProductsFromApple];
}
-(void)getProductsFromApple{
SKProductsRequest *_productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:#"2"]];
[_productRequest setDelegate:self];
[_productRequest start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
NSLog(#"Invalid %#", response.invalidProductIdentifiers);
NSLog(#"Valid %#", response.products);
if (response.invalidProductIdentifiers && [response.invalidProductIdentifiers isKindOfClass:[NSArray class]] && response.invalidProductIdentifiers.count) {
[self getProductsFromApple];
}
}
This sometimes succeeds after n calls to apple server.Our team has escalated the issue to apple, we are waiting for there response.
Has anyone faced this issue, kindly suggest how you were able to test in-apps payment ?

Display IAP Price When Device Cannot Retrieve SKProduct Price

I have an in-app purchase for my app that costs £1.99. I display this price using a pop-up, however, when the device is not connected to the internet it cannot retrieve the price of my IAP, so it shows up blank.
The price of my IAP will always be £1.99 GBP. How do I display this IAP tier for other countries when the device is not connected to the internet?
This is how I currently get the price of my IAP:
_products = nil;
[[AppIAPHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
if (success) {
_products = products;
SKProduct * product = _products[0];
[[AppIAPHelper sharedInstance] productPurchased:product.productIdentifier];
NSNumberFormatter *_priceFormatter = [[NSNumberFormatter alloc] init];
[_priceFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[_priceFormatter setLocale:product.priceLocale];
priceString = [_priceFormatter stringFromNumber:product.price];
NSLog(#"Price string: %#",priceString);
}
}];
I tried to test if priceString.count <= 0 (therefore device is not connected to the internet), and then execute:
NSDecimalNumber *amount = [NSDecimalNumber decimalNumberWithString:#"1.99"];
NSNumberFormatter *currencyFormat = [[NSNumberFormatter alloc] init];
NSLocale *locale = [NSLocale currentLocale];
[currencyFormat setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyFormat setLocale:locale];
NSLog(#"AmountSo with symbol: %#", [currencyFormat stringFromNumber:amount]);//Eg: $50.00
NSLog(#"Current Locale : %#", [locale localeIdentifier]);//Eg: en_US
But this only adds the local currecy symbol to amount.
The problem is, I need to display the correct price tiers. For example, USD 1.99 converted to GBP is 1.27. But the IAP tiers are 1.99 USD and 1.49 GBP.
So basically - how do I show the App Store IAP price tiers for the user's local currecy without requesting the price of the SKProduct (if the user is not connected to the internet)? Thanks.
You could create a property list (plist), static NSDictionary, or some other relational table containing the current price tiers mapped to country codes. If no network connection is available, grab the current locale country and use it to look up the price tier and local currency symbol.
Question though: since you can't make an in-app purchase without a network connection, why exactly do you care? Just throw a notification stating that network connection is unavailable?
One more option you could have, if you want it to be somewhat robust, is set it to cache using a policy that refreshes it if network is available, otherwise uses the cached copy. Something like this using Reachability would work, though admittedly this is for an NSURLRequest not an SKProduct request.
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus netStatus = [reachability currentReachabilityStatus];
if (netStatus == ReachableViaWiFi)
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
else
[request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];

Not sure how to invoke the buying process for in-app purchases in iOS with Objective-C

I have a method like this
- (IBAction)makePurchase:(id)sender
{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Starting the purchase"
message:#"Just press OK." delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil];
[message show];
// Put your product identifiers in an NSSet and perform the appropriate product request (i.e in viewDidLoad)
SKProductsRequest *productRequest =
[[SKProductsRequest alloc] initWithProductIdentifiers:#"2"];
productRequest.delegate = self;
[productRequest start];
NSSet *productIdentifiersForPurchase = [NSSet setWithObject:#"2"];
[[PlanIAPHelper sharedInstance] buyProduct:product];
}
The last line has a syntax error because it doesn't know what the product variable is because I didn't declare it. And that is my problem. I am not sure how to construct this object so that it gets purchased.
Would anyone be able to help me to get this to work correctly? What is the right way to make this call?
Its a bit more involved than that. I would recommend reading the In-App Purchase Programming Guide if you haven't already it can be a bit tricky to get working right.
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html
Basically you need to request the SKProducts from Apple by their identifiers. They send you the SKProduct then you use that SKProduct for the purchase. The code looks something like this.
NSSet *identifiers = [NSSet setWithObjects:#"my_product_identifier1", #"my_product_identifier_2", nil];
SKProductRequest *request = [[SKProductRequest alloc] iniWithProductIdentifiers:identifiers];
request.delegate = self;
[request start];
Then you should get a callback from the delegate method like this with the SKProducts that you requested
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductResponse *)response {
NSArray *products = response.products;
SKProduct *product = [products firstObject];
[[PlanIAPHelper sharedInstance] buyProduct:product];
}
Please excuse any mistakes, I hand-wrote this. Let me know if you have any trouble.
I've also used CargoBay https://github.com/mattt/CargoBay which is an open source wrapper around the In app purchase Framework. Makes working with IAP's much easier and also makes it super easy to validate purchases from the device which is really handy.

Still getting invalid product identifiers... iOS

I keep getting invalid product identifiers as a return from in app purchase product requests.
I've checked the following:
Checked provisioning profiles, deleted and re-made several times...
Checked product identifiers against products in itunesconnect (uk.co.companyname.appname.product_name).
Deleted app and provisions from phone and re installed.
Logged out of app store on phone.
Checked my code signing (signed as iPhone Developer (with uk.co.companyname.appname as identifier)
Made sure app identifier is in info.plist correctly.
Submitted and rejected app binary.
Running on phone, not simulator.
This is my code for fetching products:
- (void)loadProducts
{
NSSet *productIdentifiers = [NSSet setWithObjects:uk.co.companyname.appname.product_name, uk.co.companyname.appname.product_name2, uk.co.companyname.appname.product_name3, nil];
for(NSString *pk in productIdentifiers) NSLog(#"%#", pk);
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(#"products: %d", [response.products count]);
NSLog(#"invalidProductIdentifiers: %d", [response.invalidProductIdentifiers count]);
}
and I get:
products: 0
invalidProductIdentifiers: 9

Resources