I implemented in app purchases in my iOS app a while ago and they worked well for a while, but now on iOS 9 they do not work. The price does not load and then when I click the button to make the purchase, I get an alert that says "No Internet Connection". My connection is fine and it should work.
I apologize for the extremely convoluted code. I wrote this early on when I started learning programming and haven't gotten around to cleaning it up a bit.
Implementation:
I have my product ids defined in my AppDelegate as so:
#define kRemoveAdsProductIdentifier #"0991"
#define kDoubleEarningRate #"199"
#define kQuadDogecoins #"399"
#define kMegaDogecoins #"1999"
#define kAll #"5991"
kProductIdentifiers = [NSArray arrayWithObjects:kRemoveAdsProductIdentifier, kDoubleEarningRate, kQuadDogecoins, kAll, kMegaDogecoins, nil];
In IAPView.m:
-(void)didLoadFromCCB
{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
SKProductsRequest *productsRequest = [[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithArray:app.kProductIdentifiers]];
productsRequest.delegate = self;
[productsRequest start];
}
When purchase button is clicked:
-(void)removeAds{
if([SKPaymentQueue canMakePayments]){
if (validProduct != nil) {
NSLog(#"User can make payments");
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
app.appProduct = validProduct;
[app purchase:app.appProduct];
NSLog(#"Product ID: %#", app.appProduct.productIdentifier);
} else {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"No Internet Connection" message:#"You must be connected to the internet to purchase this product." delegate:self cancelButtonTitle:#"Continue" otherButtonTitles:nil, nil];
[alert show];
}
}
else{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"You do not have the ability to make payments." delegate:self cancelButtonTitle:#"Continue" otherButtonTitles:nil, nil];
[alert show];
}
}
Product request:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
validProduct = nil;
doubleEarningProduct = nil;
quadrupleDogecoins = nil;
allOfTheAbove = nil;
megaDoge = nil;
NSInteger count = [response.products count];
NSLog(#"Products.count = %li", (long)count);
if(count > 0){
validProduct = [response.products objectAtIndex:0];
doubleEarningProduct = [response.products objectAtIndex:1];
quadrupleDogecoins = [response.products objectAtIndex:3];
megaDoge = [response.products objectAtIndex:2];
allOfTheAbove = [response.products objectAtIndex:4];
_numberFormatter = [[NSNumberFormatter alloc] init];
[_numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[_numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[_numberFormatter setLocale:validProduct.priceLocale];
NSString *formattedPrice = [_numberFormatter stringFromNumber:validProduct.price];
formattedStringFinal = formattedPrice;
[adsPrice setString:formattedPrice];
formattedPrice = [_numberFormatter stringFromNumber:doubleEarningProduct.price];
formattedStringFinal = formattedPrice;
[doubleEarningLabel setString:formattedPrice];
formattedPrice = [_numberFormatter stringFromNumber:quadrupleDogecoins.price];
formattedStringFinal = formattedPrice;
[quadDogeLabel setString:formattedPrice];
formattedPrice = [_numberFormatter stringFromNumber:allOfTheAbove.price];
formattedStringFinal = formattedPrice;
[aboveLabel setString:formattedPrice];
formattedPrice = [_numberFormatter stringFromNumber:megaDoge.price];
formattedStringFinal = formattedPrice;
[megaDogeLabel setString:formattedPrice];
}
else if(!validProduct){
NSLog(#"No products available");
}
}
For some reason count gets output as 0. I got the feeling that it might be due to an error with provisioning profiles, and sure enough my provisioning profile for IAP was expired. I updated it and added it to XCode but the prices still do not load.
It works perfectly fine on my iPad (iOS 8.1), but not not on my iPhone (iOS 9).
Any ideas?
Related
I used the following code to get message from a particular beacon but it always shows null in uuid. When i run this code the "viewdidLoad method works fine but when it comes to didRangebeacons it shows only the last uuid beacons. Actually i want to check that Is beacon available for particular uuid and receive that signals and keep on checking for uuids in array and when it receives another signal it should display that beacon signal also.
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
NSLog(#"Before assigning UUID");
NSArray *uuidArr = [NSArray arrayWithObjects: #"9146947B-441D-4116-B60E-4DD4659825AB", #"9146947B-441D-4116-B60E-4DD46598257C", #"9146947B-441D-4116-B60E-4DD46598257B", nil];
for(int i=0; i<[uuidArr count]; i++)
{
NSString *uuidTemp = [uuidArr objectAtIndex:i];
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:uuidTemp];
self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:#"com.gimbal.iosexample"];
[self.locationManager startMonitoringForRegion:self.myBeaconRegion];
[self.locationManager startRangingBeaconsInRegion:self.myBeaconRegion];
if (![CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
NSString *msg = [NSString stringWithFormat:#"Monitoring not available for %#", uuidTemp];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Monitoring not available" message:msg delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show]; return;
}
}
}
-(void)locationManager:(CLLocationManager*)manager didRangeBeacons:(NSArray*)beacons inRegion:(CLBeaconRegion*)region
{
NSLog(#"iBeacons found");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Successfully found" message:nil delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
self.statusLabel.text = #"iBeacon found!";
CLBeacon *foundBeacon = [beacons firstObject];
NSString *uuid = foundBeacon.proximityUUID.UUIDString;
NSString *major = [NSString stringWithFormat:#"%#", foundBeacon.major];
NSString *minor = [NSString stringWithFormat:#"%#", foundBeacon.minor];
NSLog(#"UUID: %#", uuid);
}
#end
Can anyone help me to do this.
Thanks in advance.
You are creating different beacon regions in your for loop, but your region identifier is the same, so the second region definition will replace the first, and then the second will be replaced by the third. You need to use a unique region identifier - something like
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:[NSString stringWithFormat:#"com.gimbal.iosexample.%d",i]];
I am new to iOS programming, and just want to do something fun.
I want to develop a mail client app for iPhone, it can add email accounts such as gmail and Yahoo and so on. I searched online for a while and also find some answers, before I dive into the details I just want someone who has similar experience give me some suggestions about which method is the best.
thanks
I have recently implemented gmail api to fetch gmail contacts and their email in my tableview. Gmail api is depricated, thats why you might have not got any proper documentation for that.
To implement gmail use libGDataTouchStaticLib.a library, with Gdata headers (search on google for that otherwise send me your email i will send you its zip).
The code to get gmail details are as follows
- (void)getGoogleContacts {
GDataServiceGoogleContact *service = [self contactService];
GDataServiceTicket *ticket;
BOOL shouldShowDeleted = TRUE;
// request a whole buncha contacts; our service object is set to
// follow next links as well in case there are more than 2000
const int kBuncha = 2000;
NSURL *feedURL = [GDataServiceGoogleContact contactFeedURLForUserID:kGDataServiceDefaultUser];
GDataQueryContact *query = [GDataQueryContact contactQueryWithFeedURL:feedURL];
[query setShouldShowDeleted:shouldShowDeleted];
[query setMaxResults:kBuncha];
ticket = [service fetchFeedWithQuery:query
delegate:self
didFinishSelector:#selector(contactsFetchTicket:finishedWithFeed:error:)];
[self setContactFetchTicket:ticket];
}
- (void)setContactFetchTicket:(GDataServiceTicket *)ticket {
mContactFetchTicket = ticket;
}
- (GDataServiceGoogleContact *)contactService {
static GDataServiceGoogleContact* service = nil;
if (!service) {
service = [[GDataServiceGoogleContact alloc] init];
[service setShouldCacheResponseData:YES];
[service setServiceShouldFollowNextLinks:YES];
}
// update the username/password each time the service is requested
NSString *username = [txtUserName text];
NSString *password = [txtPasswrod text];
[service setUserCredentialsWithUsername:username
password:password];
return service;
}
// contacts fetched callback
- (void)contactsFetchTicket:(GDataServiceTicket *)ticket
finishedWithFeed:(GDataFeedContact *)feed
error:(NSError *)error {
if (error) {
NSDictionary *userInfo = [error userInfo];
NSLog(#"Contacts Fetch error :%#", [userInfo objectForKey:#"Error"]);
if ([[userInfo objectForKey:#"Error"] isEqual:#"BadAuthentication"]) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error!"
message:#"Authentication Failed"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[alertView show];
} else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error!"
message:#"Failed to get Contacts."
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[alertView show];
}
} else {
NSArray *contacts = [feed entries];
NSLog(#"Contacts Count: %d ", [contacts count]);
[mutAryGoogleContacts removeAllObjects];
for (int i = 0; i < [contacts count]; i++) {
NSMutableDictionary *aDictContactDetails=[NSMutableDictionary dictionary];
GDataEntryContact *contact = [contacts objectAtIndex:i];
// Email
GDataEmail *email = [[contact emailAddresses] objectAtIndex:0];
NSString* ContactEmail = [email address];
if (ContactEmail) {
[aDictContactDetails setObject:ContactEmail forKey:#"email"];
// Name
NSString *ContactName = [[[contact name] fullName] contentStringValue];
if (ContactName) {
[aDictContactDetails setObject:ContactName forKey:#"friendName"];
}
[mutAryGoogleContacts addObject:aDictContactDetails];
}
}
//Push to next vc or do whatever you want
}
}
Every time I try to save my NSManagedObjectContex, it takes 1-8 seconds each time. Here is my code:
- (IBAction)save
{
if (self.managedObjectContext == nil) {
self.managedObjectContext = [(RootAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
if (self.brandText.text.length == 0 || self.modelText.text.length == 0) {
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Please fill out the required fields" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(125, 40, 31, 7)];
NSString *path = [[NSString alloc] initWithString:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"bullet.png"]];
UIImage *bkgImg = [[UIImage alloc] initWithContentsOfFile:path];
[imageView setImage:bkgImg];
[alertView addSubview:imageView];
[alertView show];
} else {
Hand *a = [NSEntityDescription insertNewObjectForEntityForName:#"Hand" inManagedObjectContext:self.managedObjectContext];
a.brand = self.brandText.text;
a.caliber = self.cText.text;
self.managedObjectContext = self.app.managedObjectContext;
a.notes = self.notesView.text;
a.serialNumber = self.serialNumberText.text;
a.nickname = self.nicknameText.text;
a.model = self.modelText.text;
a.gunImage = self.image.image;
a.roundsFired = [NSString stringWithFormat:#"0"];
a.cleanRounds = [NSString stringWithFormat:#"500"];
a.showBadge = [NSNumber numberWithBool:YES];
[self dismissViewControllerAnimated:YES completion:nil];
NSError *error;
if (![self.managedObjectContext save:&error]) {
UIAlertView *errorAlert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"There was an internal error. \n Please restart the app and try again, Thank You" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[errorAlert show];
}
}
}
The code just saves the all of the textFields text. What is the reason its so slow? Any help is greatly appreciated.
Based on your question is quite difficult to understand what is going on but I would modify the else statement as follows...
else {
Hand *a = [NSEntityDescription insertNewObjectForEntityForName:#"Hand" inManagedObjectContext:self.managedObjectContext];
a.brand = self.brandText.text;
a.caliber = self.cText.text;
// why this?
// self.managedObjectContext = self.app.managedObjectContext;
a.notes = self.notesView.text;
a.serialNumber = self.serialNumberText.text;
a.nickname = self.nicknameText.text;
a.model = self.modelText.text;
a.gunImage = self.image.image;
a.roundsFired = [NSString stringWithFormat:#"0"];
a.cleanRounds = [NSString stringWithFormat:#"500"];
a.showBadge = [NSNumber numberWithBool:YES];
NSError *error;
if (![self.managedObjectContext save:&error]) { // error during saving
UIAlertView *errorAlert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"There was an internal error. \n Please restart the app and try again, Thank You" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[errorAlert show];
} else { // the save completes correctly, dismiss the view controller
[self dismissViewControllerAnimated:YES completion:nil];
}
}
If you want to monitor Core Data you should do it through Instrument. In addition you could set up Xcode as follows: XCode4 and Core Data: How to enable SQL Debugging.
Edit
Since the slow saving is due (based on your comment) to images, you should relies on these rules.
Core Data - Storing Images (iPhone)
Edit 2
Ok, since you don't know in advance about the size (in bytes) of your image, I really suggest to store the image in the filesystem and not in the Core Data store. In the db save only the path to your image. The image will be saved in background. This to prevent the UI to block.
Otherwise, if iOS 5 is the minimum requirement, use the External Storage flag.
How to enable External Storage for Binary Data in Core Data
Hope that helps.
I got app, which can send twits.
I do it in this way:
- (IBAction)twitDream:(id)sender
{
if ([TWTweetComposeViewController canSendTweet]) {
TWTweetComposeViewController *tweet =
[[TWTweetComposeViewController alloc] init];
if (dream.image != [UIImage imageNamed:#"blank-photo.png"])
[tweet addImage:dream.image];
NSString *twitMsg = [dreamField.text stringByAppendingString:#" send via Dreamer"];
[tweet setInitialText:twitMsg];
[self presentModalViewController:tweet animated:YES];
} else {
//can't tweet!
}
}
What should i do when [TWTweetComposeViewController canSendTweet] is equal to NO ? And when it is equal to NO ?
That is full solution code:
- (IBAction)twitDream:(id)sender
{
if ([TWTweetComposeViewController canSendTweet]) {
TWTweetComposeViewController *tweet =
[[TWTweetComposeViewController alloc] init];
if (dream.image != [UIImage imageNamed:#"blank-photo.png"]) {[tweet addImage:dream.image];}
NSString *twitMsg = [dreamField.text stringByAppendingString:#" #Dreamer"];
[tweet setInitialText:twitMsg];
[self presentModalViewController:tweet animated:YES];
} else {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"Sorry"
message:#"You can't send a tweet right now, make sure your device has an internet connection and you have at least one Twitter account setup"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
I have this normal code for notification alert:
- (void)saveNotification {
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil) {
UILocalNotification *notif = [[cls alloc] init];
notif.fireDate = [[datePicker date] dateByAddingTimeInterval:-20];
notif.timeZone = [NSTimeZone defaultTimeZone];
notif.alertBody = #"Evaluation Planner";
notif.alertAction = #"Details";
notif.soundName = UILocalNotificationDefaultSoundName;
notif.applicationIconBadgeNumber = 1;
NSDictionary *userDict = [NSDictionary dictionaryWithObject:reminderText.text
forKey:kRemindMeNotificationDataKey];
notif.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[notif release];
}
}
- (void)showReminder:(NSString *)text {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Reminder"
message:text delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
This works perfectly well for me but when I click onto "Details", I want it to be redirected to a particular page. Instead this only redirect to the main page of the application and I have to click through the whole app all the way to the reminder section to view it. I'm not exactly sure how to fix it. Do help me.
Thanks.
Your app delegate method application:didFinishLaunchingWithOptions: will get called with a notification payload. It's all documented well in Local and Push Notification Programming Guide.