Issue with In-App Purchase - objective-c

I'm testing my in-app purchase in sandbox mode but I dun understand why the in-app purchase alert box keeps popping up even though i've clicked Buy...
On the second time it pops up after i clicked 'Buy', i clicked 'Cancel' and there was an error:
Thread 1:EXC_BAD_ACCESS (code1, address=0x6000008)
My .m:
-(void)updateCredit{
//Adding to plist
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"data.plist"];
NSMutableArray *currPlist = [[NSMutableArray alloc] initWithContentsOfFile: path];
NSString *lastEx = [currPlist objectAtIndex:0];
int lastScore = [[currPlist objectAtIndex:1] intValue];
int numberOfTries = [[currPlist objectAtIndex:2] intValue];
int totalScore = [[currPlist objectAtIndex:3] intValue];
int avg = [[currPlist objectAtIndex:4] intValue];
int credit = [[currPlist objectAtIndex:5] intValue];
credit += 10;
NSMutableArray *updatePlist = [[NSMutableArray alloc] init];
[updatePlist addObject:lastEx];
[updatePlist addObject:[NSNumber numberWithInt:lastScore]];
[updatePlist addObject:[NSNumber numberWithInt:numberOfTries]];
[updatePlist addObject:[NSNumber numberWithInt:totalScore]];
[updatePlist addObject:[NSNumber numberWithInt:avg]];
[updatePlist addObject:[NSNumber numberWithInt:credit]];
[updatePlist writeToFile: path atomically:YES];
}
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStatePurchased:
[[SKPaymentQueue defaultQueue]finishTransaction:transaction];
[self updateCredit];
[self dismissModalViewControllerAnimated:YES];
break;
case SKPaymentTransactionStateRestored:
[[SKPaymentQueue defaultQueue]finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
if (transaction.error.code != SKErrorPaymentCancelled) {
UIAlertView *alert2 = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Error updating credit" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert2 show];
}
[[SKPaymentQueue defaultQueue]finishTransaction:transaction];
break;
default:
break;
}
}
}

Related

How to handle the UIActivityViewController "Cancel" button

There is a "cancel" button that comes by default with UIActivityViewController. How can I call a method when that button is pressed?
I have written this code to share the audio file.
NSURL* outURL;
UIActivityViewController *controller;
if (&UIActivityTypeAirDrop != NULL) {
controller.excludedActivityTypes = #[UIActivityTypeAirDrop];
for (int i=0;i<[arrayselecturls count];i++) {
str_SongsselectName=[[arrayselecturls objectAtIndex:i] objectForKey:#"Song"];
NSString* ext = [TSLibraryImport extensionForAssetURL:[[arrayselecturls objectAtIndex:i] objectForKey:#"SongURl"]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
outURL = [[NSURL fileURLWithPath:[documentsDirectory stringByAppendingPathComponent:[[arrayselecturls objectAtIndex:i] objectForKey:#"Song"]]] URLByAppendingPathExtension:ext];
NSString *str_selectfilename=[NSString stringWithFormat:#"%#.mp3",str_SongsselectName];
// NSURL *url = outURL;
// NSLog(#"url is %#",url);
NSArray *objectsToShare = [NSArray arrayWithObjects:outURL,str_selectfilename, nil];
// objectsToShare = #[outURL];
controller = [[UIActivityViewController alloc] initWithActivityItems:objectsToShare applicationActivities:nil];
// Exclude all activities except AirDrop.
NSArray *excludedActivities = #[UIActivityTypePostToTwitter, UIActivityTypePostToFacebook,
UIActivityTypePostToWeibo,
UIActivityTypeMessage, UIActivityTypeMail,
UIActivityTypePrint, UIActivityTypeCopyToPasteboard,
UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList, UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo, UIActivityTypePostToTencentWeibo];
controller.excludedActivityTypes = excludedActivities;
}
[self presentViewController:controller animated:YES completion:nil];
}
else{
UIAlertView *Alert = [[UIAlertView alloc] initWithTitle:#"Sorry" message:#"Your device has no Airdrop!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[Alert show];
}
oooooop!
I got the solution.This solution is working fine for me.
-(IBAction)ActionArtsist_airdropClick:(id)sender{
view_shareView.hidden=YES;
borderImageView . hidden =YES;
darkBg . hidden =YES;
view_artistdarlView.hidden=YES;
tblv_albumSongTableView.userInteractionEnabled=YES;
Data = [NSData dataWithContentsOfURL: exportURL];
UIActivityViewController *controller;
if (&UIActivityTypeAirDrop != NULL) {
controller.excludedActivityTypes = #[UIActivityTypeAirDrop];
NSString *str_selectfilename;
for (int i=0;i<[arr_atistsongsSelct count];i++) {
str_songsSlelectName=[[arr_atistsongsSelct objectAtIndex:i] objectForKey:#"songsName"];
NSString* ext = [TSLibraryImport extensionForAssetURL:[[arr_atistsongsSelct objectAtIndex:i] objectForKey:#"songsURl"]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSURL* outURL = [[NSURL fileURLWithPath:[documentsDirectory stringByAppendingPathComponent:[[arr_atistsongsSelct objectAtIndex:i] objectForKey:#"songsName"]]] URLByAppendingPathExtension:ext];
str_selectfilename=[NSString stringWithFormat:#"%#.mp3",str_songsSlelectName];
NSArray *objectsToShare = [NSArray arrayWithObjects:outURL,str_selectfilename, nil];
controller = [[UIActivityViewController alloc] initWithActivityItems:objectsToShare applicationActivities:nil];
// Exclude all activities except AirDrop.
NSArray *excludedActivities = #[UIActivityTypePostToTwitter, UIActivityTypePostToFacebook,
UIActivityTypePostToWeibo,
UIActivityTypeMessage, UIActivityTypeMail,
UIActivityTypePrint, UIActivityTypeCopyToPasteboard,
UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList, UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo, UIActivityTypePostToTencentWeibo];
controller.excludedActivityTypes = excludedActivities;
}
This is the handling function.
**[controller setCompletionHandler:^(NSString *activityType, BOOL completed) {
if (!completed)
{
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[self performSelector:#selector(ActiviHideArtistSong) withObject:self afterDelay:4.0 ];
}
return;
}];**
upto here
[self presentViewController:controller animated:YES completion:nil];
}
else{
UIAlertView *warningAlert = [[UIAlertView alloc] initWithTitle:#"Sorry" message:#"Your device has no Airdrop!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[warningAlert show];
}
}
-(void)ActiviHideArtistSong{
[self btnimageArtistSongscheck_lick:nil];
}

Index 1 beyond bounds

I am splitting a string into characters in an array, depending on the character an action is performed. If the textfield is blank or has 1 character in it the app crashed with a NSRangeException. If there are 2 or more characters then it works with no issues, partial code as follows:
-(IBAction) text: (id) sender{
//labelText.text = [[NSString alloc] initWithFormat:#"%#",textField1];
labelText.text = textField1.text;
NSString *myString = textField1.text;
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[myString length]];
for (int i=0; i < [myString length]; i++) {
NSString *ichar = [NSString stringWithFormat:#"%c", [myString characterAtIndex:i]];
[characters addObject:ichar];
}
//NSLog (#"%#", [characters objectAtIndex:1]);
//NSLog (#"%#", [characters objectAtIndex:2]);
one1.text = (#"%#", [characters objectAtIndex:1]);
if ([textField1.text length] == 0) {
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:#"Please enter number in the box above." message:#"" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[myAlert show];
[myAlert release];
}
else if ([textField1.text length] == 1){
NSString *char1 = [characters objectAtIndex:0];
Charr1 = char1;
}
else if ([textField1.text length] == 2){
NSString *char1 = [characters objectAtIndex:0];
NSString *char2 = [characters objectAtIndex:1];
Charr1 = char1;
Charr2 = char2;
}else if ([textField1.text length] == 3){
NSString *char1 = [characters objectAtIndex:0];
NSString *char2 = [characters objectAtIndex:1];
NSString *char3 = [characters objectAtIndex:2];
Charr1 = char1;
Charr2 = char2;
Charr3 = char3;
}else if ([textField1.text length] == 4){
NSString *char1 = [characters objectAtIndex:0];
NSString *char2 = [characters objectAtIndex:1];
NSString *char3 = [characters objectAtIndex:2];
NSString *char4 = [characters objectAtIndex:3];
Charr1 = char1;
Charr2 = char2;
Charr3 = char3;
Charr4 = char4;
}else if ([textField1.text length] == 5){
NSString *char1 = [characters objectAtIndex:0];
NSString *char2 = [characters objectAtIndex:1];
NSString *char3 = [characters objectAtIndex:2];
NSString *char4 = [characters objectAtIndex:3];
NSString *char5 = [characters objectAtIndex:4];
Charr1 = char1;
Charr2 = char2;
Charr3 = char3;
Charr4 = char4;
Charr5 = char5;
this line in your code crashes your app because if there is a 0 or 1 character in your string then your string you cannot access at location:1
one1.text = (#"%#", [characters objectAtIndex:1]);
to resolve put your whole code after for loop in following if condition
if([characters count] > 0)
{
// your code after for loop write here
}
You just forgot to remove this line:
one1.text = (#"%#", [characters objectAtIndex:1]);

Memory don't release

Here is my code:
-(void) encodeStationsBack
{
if (context == nil)
{
context = [(radioAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", context);
}
// here is JSON parsing
int i=0;
int count = stations.count;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Station" inManagedObjectContext:context];
NSMutableArray* parsedData = [[NSMutableArray alloc] init];
while(stations.count > 0) {
NSString*string = [[NSString alloc] initWithString:[stations objectAtIndex:0]];
if (![string isEqual:#""]) {
NSMutableDictionary*dic = [[NSMutableDictionary alloc]init];
// NSLog(#"%#", string);
NSData*data = [[NSData alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]];
NSMutableDictionary* pars;
#try {
pars = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}
#catch (NSException *exception) {
NSLog(#"%# , %#", exception.description, exception.reason);
}
#finally {
}
// NSMutableDictionary* pars =[[NSMutableDictionary alloc]initWithDictionary:[NSJSONSerialization JSONObjectWithData:data
// options:kNilOptions/*NSJSONReadingMutableContainers*/ error:nil]];
[pars retain];
[dic setObject:[[pars objectForKey:#"nm"]mutableCopy] forKey:#"nm"];
[dic setObject:[[pars objectForKey:#"btr"]mutableCopy] forKey:#"btr"];
[dic setObject:[[pars objectForKey:#"id"]mutableCopy] forKey:#"id"];
[dic setObject:[[pars objectForKey:#"cntr"]mutableCopy] forKey:#"cntr"];
[dic setObject:[[pars objectForKey:#"gnr"]mutableCopy] forKey:#"gnr"];
[pars release];
#try {
[parsedData addObject:[NSDictionary dictionaryWithDictionary:dic]];
}
#catch (NSException* exc) {
NSLog(#"%#, %#", exc.description, exc.reason);
}
[dic release];
[data release];
[string release];
[stations removeObjectAtIndex:0];
// if (i%1000==0) {
// NSLog(#"nnnn %i %i", parsedData.count, stations.count);
// }
i++;
float k = count;
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
}
else {
[stations removeObjectAtIndex:0];
}
}
[stations release];
i = 0;
while (parsedData.count > 0) {
Station*station = [[Station alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
[station setName:[[[parsedData objectAtIndex:0] objectForKey:#"nm"]mutableCopy]];
[station setBit:[[[parsedData objectAtIndex:0] objectForKey:#"btr"]mutableCopy]];
[station setEnabled:[NSNumber numberWithInt:1]];
//encoding id of the station
unsigned int tempInt;
NSScanner *scanner= [[NSScanner alloc] init];
scanner = [NSScanner scannerWithString:[[parsedData objectAtIndex:0] objectForKey:#"id"]];
[scanner scanHexInt:&tempInt];
NSNumber *numb = [[NSNumber alloc] init];
numb = [NSNumber numberWithInt:tempInt];
numb = [NSNumber numberWithInt: ([numb integerValue] ^ sec )];
[station setNumber: [NSNumber numberWithInt:[numb intValue]]];
//encoding country ID
tempInt = 0;
scanner = [NSScanner scannerWithString:[[parsedData objectAtIndex:0] objectForKey:#"cntr"]];
[scanner scanHexInt:&tempInt];
numb = [NSNumber numberWithInt:tempInt];
numb = [NSNumber numberWithInt:(([numb integerValue] ^ sec ))];
if (![numb isEqualToNumber:[NSNumber numberWithInt:n]])
{
[station setCountryID:[NSNumber numberWithInt:[numb intValue]]];
}
else
{
[station setCountryID:[NSNumber numberWithInt:-1]];
}
//encoding genre ID
tempInt = 0;
scanner = [NSScanner scannerWithString:[[parsedData objectAtIndex:0] objectForKey:#"gnr"]];
[scanner scanHexInt:&tempInt];
numb = [NSNumber numberWithInt:tempInt];
numb = [NSNumber numberWithInt:(([numb integerValue] ^ sec ))];
if (![numb isEqualToNumber:[NSNumber numberWithInt:N]])
{
[station setGenerID:[NSNumber numberWithInt:[numb intValue]]];
}
else
{
[station setGenerID: [NSNumber numberWithInt:-1]];
}
[station setOrder:[NSNumber numberWithInt:i]];
[context insertObject:station];
float k = count;
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
// NSLog(#"%i", i);
[parsedData removeObjectAtIndex:0];
[station release];
// [station release];
i++;
}
[parsedData release];
[self performSelectorOnMainThread:#selector(deleteAllFromDB) withObject:nil waitUntilDone:YES];
[context save:nil];
}
I can't understand why my app uses so mutch memory (~150 mb). I tryed to look on my code with analyze. Nothing interestig xCode thinks that all is ok.
Here is what I see with Instruments
Instruments
you have alloced in the loop and de alloced outside the loop in scanner there are other mistakes like this. have a look and make a code review.
id obj1 =[[pars objectForKey:#"nm"]mutableCopy];
[dic setObject:obj1 forKey:#"nm"];
[obj1 release]; // No memory leak
[dic setObject:[[pars objectForKey:#"btr"]mutableCopy] forKey:#"btr"];//memory leak
[dic setObject:[[pars objectForKey:#"id"]mutableCopy] forKey:#"id"];//memory leak
[dic setObject:[[pars objectForKey:#"cntr"]mutableCopy] forKey:#"cntr"];//memory leak
[dic setObject:[[pars objectForKey:#"gnr"]mutableCopy] forKey:#"gnr"];//memory leak
Change all setObject:forKey:

how to show uialertview in another thread in objective c

I created another thread and its functionality is working well. But only case is in new thread we cannot use UIControllers. As an example I couldn't use UIAlerview in new thread. How can I slove it?
My tried code is bellow.
- (IBAction)btnCopyImage:(id)sender
{
[NSThread detachNewThreadSelector:#selector(DownloadCheck) toTarget:self withObject:nil];
// [self performSelectorOnMainThread:#selector(DownloadCheck) withObject:nil waitUntilDone:NO];
NSLog(#"My name is ");
int sum =0;
for (int i=1; i<=1000; i++)
{
sum =sum+i;
}
NSLog(#"sum %d",sum);
}
-(void)DownloadCheck
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Download"];
NSString* saveDialogURL = #"/Volumes/Inbox/7. Debugging and Troubleshooting.zip";
NSString* fileNameWithExtension = saveDialogURL.lastPathComponent;
NSLog(#"path %# ",fileNameWithExtension);
NSString *pathWithExtention=[NSString stringWithFormat:#"%#/%#", path,fileNameWithExtension];
NSLog(#"path %#",pathWithExtention);
//Remove existing file
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
NSError *error;
[filemgr removeItemAtPath:pathWithExtention error:&error];
//Copy file to i phone created directory
if ([filemgr copyItemAtPath: saveDialogURL toPath: pathWithExtention error: NULL] == YES)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Download"
message:#"Downloaded Sucessfully"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"OK", nil];
[alertView show];
NSLog (#"Copy successful");
}
else
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Download Faild"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"OK", nil];
[alertView show];
NSLog (#"Copy Faild");
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
[self performSelectorOnMainThread:#selector(DownloadCheck) withObject:nil waitUntilDone:NO]; this cannot be used because it's working on same thread.
So what should I do by using same code?

Repeating UIAlert code over and over

I have this code:
-(IBAction)action2:(id)sender{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Confirm" message:#"If you press of a new group with the name you have set will be created" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles: #"Ok", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Ok"])
{
NSString *destDir = [NSString stringWithFormat:#"/sandbox/%#/", namegroup.text];
NSString *filename5 = namegroup.text;
NSString *filename6 = #"group";
NSString *filename7 = #"groupdata";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *getImagePath5 = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat:#"%#", filename7]];
NSMutableArray *titles = [NSMutableArray array];
[titles addObject:filename5];
NSMutableArray *keys = [NSMutableArray array];
[keys addObject:filename6];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:titles forKeys:keys];
NSString *jsonString = [dict JSONRepresentation];
NSData *jsonData = [jsonString dataUsingEncoding: NSUTF8StringEncoding];
[jsonData writeToFile: getImagePath5 atomically: YES];
[[self restClient] uploadFile:filename7 toPath:destDir
withParentRev:nil fromPath:getImagePath5];
}
}
If I press Ok button, the code is repeated over and over. how can I repeat it only 1 time??
I found out that there was another alert with the same cancel title, and when this was pressed it re-launched the same code. Thanks however for the help.