SKProduct attributes throw exc_bad_access - iphone

I'm implementing in app purchase in my app. I created a product at itunes and also product requesting functions in code successfully. the product returns. the problem is that i cannot access any of the attributes of the prouct (localizedTitle, price etc.). It allways throws exc_bad_access. here's my code:
NSMutableArray *myProduct = [[NSMutableArray alloc] init];
[myProduct addObjectsFromArray:response.products];
if(myProduct != nil && [myProduct count] > 0)
{
SKProduct *subscriptionProduct = [myProduct objectAtIndex:0];
if(subscriptionProduct != nil)
{
if(subscriptionProduct.localizedTitle != nil)
NSLog("%#",subscriptionProduct.localizedTitle); /***EXC_BAD_ACCESS** */
}
}
[request autorelease];
I set NSZombieEnabled YES, but still no explanation for exc_bad_access.
I'll be glad if someone has an answer.
Thanks in advance.

You've forgotten to put an # symbol before your NSLog format string:
NSLog(#"%#",subscriptionProduct.localizedTitle); /***EXC_BAD_ACCESS** */

Related

NSDictionary init with object for keys

NSLog(#"1");
NSArray *obj= [NSArray arrayWithObjects:appDel.token, nil];
NSLog(#"2");
NSArray *key= [NSArray arrayWithObjects:#"Token", nil];
NSLog(#"3");
NSDictionary *d= [[NSDictionary alloc] initWithObjects:obj forKeys:key];
NSLog(#"4");
DoSomething();
NSLog(#"5");
Need help with the above code. I seem to be crashing on #"4" (it does not print 4).
The error from Xcode:
'Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ' -[NSDictionary initWithObjects:forKeys:]: count of objects (0) differs from count of keys (1)'
Any kind soul can point me in the right direction? It use to work till i upgraded to Xcode 5 :(
I'm most certain of the fact that NSLog(#"%#", appDel.token); will display (null), because your token is nil. Verify that appDel.token isn't nil, and you won't be getting that error.
Hope this helps.
Your appDel.token is nil. Add the below reusable method in your project utility.
-(BOOL)isObjectEmpty:(id)object
{
return object == nil || ([object respondsToSelector:#selector(length)] && [(NSData *)object length] == 0) || ([object respondsToSelector:#selector(count)] && [(NSArray *)object count] == 0);
}

Having trouble comparing two strings from Twitter API on iPhone

I'm trying to get tweets using the Twitter API, but for some reason this problem is coming up whenever I try to refresh the tweets:
[__NSCFDictionary isEqualToString:]: unrecognized selector sent to instance 0x6c22e70
Getting tweets for the first time and filling "tweetssofar" is happening properly, and when I NSLog fromtwitternew and existingtwitter, both are showing the same thing. Both are strings that are actually dictionaries, but why cannot I compare them this way? Thanks!
- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier {
NSString *fromtwitternew = [statuses objectAtIndex:0];
NSString *existingtwitter = [tweetssofar objectAtIndex:0];
NSLog(#"No problem so far");
if ([fromtwitternew isEqualToString:existingtwitter]) { //No new tweets
NSLog(#"No new tweets");
contents = [[NSDictionary alloc] init];
contents = [tweetssofar objectAtIndex:counter];
}
isEqualToString: only works for strings, and those tweets are probably json or xml strings parsed into dictionaries by a parser. If you want to know whether two parsed tweets are equal, you can compare them like this:
[[tweetA valueForKey:#"id"] isEqualToNumber:[tweetB valueForKey:#"id"]];
#Prajoth with the following code , I am sure you will be able to fix your problem
- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier {
if ([statuses count] > 0 && [tweetssofar count] > 0) {
id fromtwitternew = [statuses objectAtIndex:0];
if ([fromtwitternew isKindOfClass:[NSDictionary class]]) {
//Handle code accroding to Dictionary Results
contents = [[NSDictionary alloc] init];
contents = [tweetssofar objectAtIndex:counter];
}
else if ([fromtwitternew isKindOfClass:[NSString class]]) {
//Make Sure that you have added Only Strings to tweetssofar , in case You have added dictionary you can not use isEqualToString
NSString *existingtwitter = [tweetssofar objectAtIndex:0];
if ([fromtwitternew isEqualToString:existingtwitter]) { //No new tweets
NSLog(#"No new tweets");
}
}
}
}
The Crash is most probably because you are comparing isEqualToString: Method to compare two dictionary objects which you should not be doing. In case you need to compare two tweets you should first extract the Strings from dictionary and then compare them.

Check if key exists in NSDictionary is null or not

I did search on how to check if NSDictionary key exists or not and came up with the solution. But still it throws me an error saying adding null value to the key.
I am not sure if my code is correct or not. If anyone has any idea about this can help me.
NSDictionary *result;
id myImageURL = [result objectForKey:#"url"];
if ((NSNull *)myImageURL == [NSNull null])
myImageURL = #"";
id myImage = [result objectForKey:#"image"];
if ((NSNull *)myImage == [NSNull null])
myImage = #"";
Check if null add nothing and if not add the value. But it still gives me an error dont know why.
/****OUTPUT*****/
2011-08-11 14:56:06.668 Tab_Table_Win[6510:207] RESULTS : {
image = "<UIImage: 0xbc332c0>";
url = "http://a3.twimg.com/profile_images/999228511/normal.jpg";
}
2011-08-11 14:56:06.669 Tab_Table_Win[6510:207] url : http://a3.twimg.com/profile_images/999228511/normal.jpg
2011-08-11 14:56:06.670 Tab_Table_Win[6510:207] IMage : <UIImage: 0xbc332c0>
/*****Breaks Here ***/
2011-08-11 14:56:06.876 Tab_Table_Win[6510:207] RESULTS : {
}
2011-08-11 14:56:06.878 Tab_Table_Win[6510:207] url : (null)
2011-08-11 14:56:06.879 Tab_Table_Win[6510:207] IMage : (null)
2011-08-11 14:56:06.881 Tab_Table_Win[6510:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil key'
Correct answer is :
NSDictionary *result;
NSURL *myImageURL = [result objectForKey:#"url"];
UIImage *myImage = [result objectForKey:#"image"];
/**** Correct way ****/
if (myImageURL != nil && myImage != nil) {
[images setObject:myImage forKey:myImageURL];
}
Thank you for all the explanation.
Tommy explained this perfectly.
What I recommend is create an extension of the NSDictionary class like:
#import <Foundation/Foundation.h>
#interface NSDictionary (Safety)
- (id)safeObjectForKey:(id)aKey;
#end
And the implementation file:
#import "NSDictionary+Safety.h"
#implementation NSDictionary (Safety)
- (id)safeObjectForKey:(id)aKey {
NSObject *object = self[aKey];
if (object == [NSNull null]) {
return nil;
}
return object;
}
#end
And instead of using [dictionary objectForKey:#"keyName"]; in your code, use
[dictionary safeObjectForKey:#"keyName"];
This way, as Tommy explained, you'd be sending a method call to a nil which wouldn't crash the app but your object would get a nil value.
Hope this helps.
Whenever I try to check if an object being returned from a dictionary is null, I do this:
id obj = [myDictionary objectForKey:entityKeyName];
if (obj == [NSNull null]) {
// do something
}
Then in your code, it would be:
NSDictionary *result;
NSString *myImageURL = [result objectForKey:#"url"];
if (myImageURL == [NSNull null])
myImageURL = #"";
That's what I would do in your code.
Also, just making sure, is the NSDictionary result defined? In your code, it doesn't have anything it's being set to. It's just being defined as variable you plan on using called results
the answer below worked for me:
https://stackoverflow.com/a/2784675/936957
if ([dictionary objectForKey:key]) {
// previously stored data for "key"
}
Also note that you can get array of the keys in a dictionary using
[dictionary allKeys]
If an object doesn't exist for a key, NSDictionary will return nil. An NSNull is an actual object, and therefore a distinct thing. It's like the distinction between being able to record that there was a value and the value as null, and not recording whether there was a value. It also rests a bit on you thinking in C terms of the indirection of a pointer to an object rather than just an object, so it's not completely semantically pleasing from that perspective.
In Objective-C, you may send any message to nil and the result is guaranteed to be nil (or 0). So if your code is designed to ensure that you have a safe object reference, as you might in C++, then what you're doing is unnecessary. Compound statements like:
object = [[Type alloc] init];
Are always explicitly safe, even if alloc fails and returns nil. All that'll happen is that the call to init won't do anything at all, and object will end up with the value nil because the result of sending of init to nil is also nil.
That being said, the answers provided by Bill and Emmanuel should be correct. Compare your result either directly to nil or implicitly to zero. If you're getting a crash later on, I'll guess it's because you're expecting myImageUrl and myImage to be types other than NSString (I notice you've used the typeless id in your original code) and sending them a message they don't respond to.
NSDictionary *result;
NSString *myImageURL = [result objectForKey:#"url"];
if (myImageURL == NULL)
myImageURL = #"";
NSString *myImage = [result objectForKey:#"image"];
if (myImageURL == NULL)
myImage = #"";
See if that works, rather than overthinking the NULL class.
this another option:
if (![result objectForKey:#"image"])
{
NSLog(#"doesn't exist");
}
if ([result objectForKey:#"image"])
{
NSLog(#"exist");
}
that was not work for me, i figured it out like this
id myImageURL = [result objectForKey:#"url"];
if ([myImageURL isKindOfClass:[NSNull class]])
myImageURL = #"";
Alright here's the actual answer which #Iomec almost had
UIImage *myImage = ([result objectForKey:#"image"] != [NSNull null] ? [result objectForKey:#"image"] : nil);
That is the actual correct answer because, it comes as null and when you say myImage = [receivedObject...]; then if myImage = nil, you are in effect casting a null value(nil) into a class which is an exception, if not a running bug.
You should:
1) test for NSNull null value
2) if not nil then assign
If you code hasn't bugged out yet, it will in production when you have 8 apps running in the background one day.
I got the same issue with JSONKit. The implementation there is
- (id)objectForKey:(id)aKey
{
[...]
return((entryForKey != NULL) ? entryForKey->object : NULL);
}
So this will definitely return NULL if the object isn't there. I check it like the following
NSArray* array = [myDictionary objectForKey:#"a"];
if((NSNull*)arrays!=[NSNull null])
{
[...]
}
1. Results Dictionary after JSON parsing:
//if hits success
{"result":{"action":"authentication","statusCode":"200","statusMsg":"No
error, operation
successful.","count":1,"data":{"apiToken":"509e6d21-4f69-4ded-9f3d-4537e59e6a3a","userId":8,"role":"Bidder","firstName":"bidder","lastName":"bidder","emailAddress":"1cbrecbill#wricapitalgroup.com","countiesCovered":"21,16,11,1,2,14,32,3,4,25,13,15,5,41,43,6,12,7,24,39,17,36,42,44,29,40,8,18,19,27,9,28,23,10,33,26,35,20,30,22,34,31"}}}
//Data is Dictionary inside Result
-----------------------------------------------------------------------
I had an error showing : NULL DATACould not cast value of type 'NSNull' (0xda7058) to 'NSDictionary' (0xda6d74) and the result was
the following.
({"result":{"action":"authentication","statusCode":"204","statusMsg":"Invalid
Username or Password","count":null,"data":null}})
I fixed the Null check of dictionary.
if (result.objectForKey("data") is NSNull)
{
print ("NULL DATA")
}
else
{
let data = result["data"]as! NSDictionary
print (data)
}
Might want to add a bit more safety by checking to make sure it is NOT a string instead of just checking if it IS a nil. (To make sure it is not a number or anything else you might not want.)
id myImageURL = [result objectForKey:#"url"];
if (![myImageURL isKindOfClass:[NSString class]]) {
myImageURL = #"";
}
When you call objectForKeyin nullable dictionary, app gets crashed so I fixed this from this way to avoid from crash.
- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
id object = dictionary;
if (dictionary && (object != [NSNull null])) {
self.name = [dictionary objectForKey:#"name"];
self.age = [dictionary objectForKey:#"age"];
}
return self;
}

iPhone memory leak because of stringWithUTF8String

i have the following code which shows memory leak for object favorite near the statement with stringWithUTF8String.
i have declared favorites in the property
-(NSMutableArray *) readFavoritesFromDatabase
{
// Check if database is present
[self setDatabaseNameAndPath];
[self checkAndCreateDatabase];
// Setup the database object
sqlite3 *database;
//Initialize favorites array
if (favorites == nil)
{
[favorites release];
favorites = [[NSMutableArray alloc] init];
}
else
{
favorites = nil;
[favorites removeAllObjects];
}
// Open the database from the users file system
if(sqlite3_open([self.dataBasePath UTF8String], &database) == SQLITE_OK)
{
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "select * from Favorites";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
// Loop through the results and add them to the favorites array
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
// Create Favorite object and add it to the Favorite array
Favorite *favorite = [[[Favorite alloc] init] autorelease];
favorite.cameraID = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(compiledStatement, 0)];
favorite.cameraName = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(compiledStatement, 1)];
favorite.cameraLink = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(compiledStatement, 2)];
[self.favorites addObject:favorite];
//[favorite.cameraID release];
// [favorite.cameraName release];
// [favorite.cameraLink release];
}
// If favorite cameras exists in database, then sort the Favorites array
if([self.favorites count]>0)
{
NSSortDescriptor *favoritesNameSorter = [[NSSortDescriptor alloc] initWithKey:#"cameraName" ascending:YES];
[self.favorites sortUsingDescriptors:[NSArray arrayWithObject:favoritesNameSorter]];
[favoritesNameSorter release];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
// Close the database
if(database !=nil)
{
sqlite3_close(database);
return self.favorites;
}
else
{
return nil;
}
}
Please let me know how to solve this memory leak problem
Thanks in advance.
Use this safe method:
Favorite *tempFavorite = [[Favorite alloc] init];
self.favorite = tempFavorite;
[tempFavorite release];
Normaly, in your Favorite dealloc function, you should remove all objects and clean what necessary before calling the super dealloc function.
Using this way, you don't need to worry about if favorite is nil or not since objective-c allows calling methods for nil objects
Regards
Meir Assayag
Not sure about the stringWithUTF8String leak, but this is a problem:
favorites = nil;
[favorites removeAllObjects];
You leak what was in favorites and then tell a nil object to remove all objects -- it's nil, by definition it has none. Then later on you try to add objects to it; that won't work either.
I don't see any leak in your stringWithUTF8String, that code works well. However, look at the whole method, I found something can create memory problems like leaking or crashing. If you already declared a property for favorites, then you should use self.favorites here
//Initialize favorites array
if (favorites == nil)
{
[favorites release];
favorites = [[NSMutableArray alloc] init];
}
else
{
favorites = nil;
[favorites removeAllObjects];
}
becomes:
//Initialize favorites array
if (self.favorites == nil)
{
self.favorites = [[NSMutableArray alloc] init];
}
else
{
self.favorites = nil;
}
It will help you a lot of things in memory managements, like in your else condition, you set the variable to nil but not release it, and in the first condition, you release a nil object?

string value stored in NSDictionary

I am trying to implement this button action, but the if statement is not evaluating to be true. I have a situation where the value in that "School" dictionary will not always have a website stored. For that reason i want to check, but what do i check against. If "nil" is not stored there when there is not a value, then what is?
-(IBAction) btnVisitWebsite_clicked :(id)sender {
if([School objectForKey:WEBSITE_KEY] == nil){
UIAlertView *NoWebsite = [[UIAlertView alloc]initWithTitle: #"No Website"
message:#"The selected school has not listed a website"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
NoWebsite.tag = 15;
[NoWebsite show];
[NoWebsite release];
NoWebsite = nil;
}
else{
NSMutableString *WebsiteVisit = [[NSMutableString alloc] initWithString: #"http://"];
[WebsiteVisit appendString:[School objectForKey:WEBSITE_KEY]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: WebsiteVisit]];
[WebsiteVisit release];
}
}
If it is possible that the Website is an empty string you should use the following:
if(![School objectForKey:WEBSITE_KEY]
|| ([[School objectForKey:WEBSITE_KEY] isKindOfClass:[NSString class]] && [(NSString*)[School objectForKey:WEBSITE_KEY] length]==0)){
// no website
} else { /* has website*/ }
Have you tried to use NSLog to print the object for the key ?
NSLog(#"School[WEBSITE_KEY]=<%#>", [School objectForKey:WEBSITE_KEY]);
Maybe it is not nil ?
See if the requested school is in the NSDictionary by checking if it has an entry
BOOL containsKey = [[School allKeys] containsObject:WEBSITE_KEY];
If there is no school website, there should not be an directory entry for the WEBSITE_KEY.
An NSDictionary cannot contain nil. If the key exists it has to contain an object. The objectForKey: method will return nil if there is no object defined for a specific key. You can however store [NSNull null] as a null placeholder in a dictionary or array. So you can check for that, it all depends how your dictionary is populated.
[School objectForKey:WEBSITE_KEY] == nil || [School objectForKey:WEBSITE_KEY] == [NSNull null]
Also ensure you're not confusing #"" with a nil or no value. If it's not nil and not [NSNull null] then it's best to log it, and perhaps look at what object is being stored:
NSLog(#"Description: %#", [School objectForKey:WEBSITE_KEY]);
NSLog(#"Class: %#", [[School objectForKey:WEBSITE_KEY] class]);
If the class returns a NSString or NSCFString then it looks like it contains an empty string. Which you can check for. Here is the full blown statement:
id schoolWebsite = School objectForKey:WEBSITE_KEY];
if (schoolWebsite && schoolWebsite != [NSNull null] && [schoolWebsite isKindOfClass:[NSString class]] && [schoolWebsite length] > 0)) {
// There is definitely a non-empty string for that key!
} else {
// Not valid
}
This will be good to use as you may be unsure of exactly what is stored in the dictionary as others will be populating it. You can never be too careful!