'NSInvalidArgumentException', reason: '*** setObjectForKey: object cannot be nil (key: device_uid)' - ios

I have an error when trying to run the application on my iPhone. I don't understand why I have a nil error in this case
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ' setObjectForKey: object cannot be nil (key: device_id)'
First throw call stack: (0x183ce0f48 0x19918bf80 0x183bcc4e0 0x10006f5f0 0x1002b9ca8 0x1002b9c68 0x1002bf710 0x183c981f8 0x183c96060 0x183bc4ca0 0x18f148088 0x1892dcffc 0x1000716a0 0x1999ce8b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
Here is the part of appdelegate.m file concerned by this error :
// Get the users Device Model, Display Name, Token & Version Number
UIDevice *device = [UIDevice currentDevice];
NSUserDefaults *dict = [NSUserDefaults standardUserDefaults];
NSString *identifier = [dict stringForKey:#"identifier"];
NSString *deviceName = device.name;
NSString *deviceModel = device.model;
NSString *deviceSystemVersion = device.systemVersion;
// Prepare the Device Token for Registration (remove spaces and < >)
NSString *deviceToken = [[[[token description]
stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSMutableDictionary *postDatas = [NSMutableDictionary dictionary];
[postDatas setObject:appName forKey:#"app_name"];
[postDatas setObject:appVersion forKey:#"app_version"];
[postDatas setObject:identifier forKey:#"device_uid"];
[postDatas setObject:deviceToken forKey:#"device_token"];
[postDatas setObject:deviceName forKey:#"device_name"];
[postDatas setObject:deviceModel forKey:#"device_model"];
[postDatas setObject:deviceSystemVersion forKey:#"device_version"];
[postDatas setObject:pushBadge forKey:#"push_badge"];
[postDatas setObject:pushAlert forKey:#"push_alert"];
[postDatas setObject:pushSound forKey:#"push_sound"];
Request *request = [Request alloc];
request.delegate = self;
[request postDatas:postDatas withUrl:#"push/iphone/registerdevice/"];
is this method deprecated?

You are getting nil in the identifier. So please check it like this
NSString *identifier = [dict stringForKey:#"identifier"];
if([identifier length] != 0)
[postDatas setObject:identifier forKey:#"device_uid"];
else
[postDatas setObject:#"" forKey:#"device_uid"];

You cannot put nil values into a dictionary. It will crash.
What you really need to investigate: Where do these nil values come from, and what is the appropriate thing to do when you get nil values? That's something only you can decide. Mukesh's answer should you how to store an empty string instead of nil. This avoids the crash. It often is the correct thing to do, but not always. So investigate what your app should do if one of the values is nil, and make it do exactly that.

Related

Error while converting nsdata to nsstring

I'm trying to convert NSData to NSString
Here's my code
NSData *Data = [[NSUserDefaults standardUserDefaults] objectForKey:#"phoneNumber"];
NSString *getPhone = [NSString stringWithUTF8String:[Data bytes]];
NSLog(#"%#",getPhone);
And the error I'm getting is
-[__NSCFData rangeOfString:]: unrecognized selector sent to instance
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFData rangeOfString:]: unrecognized selector sent to instance
Make the following change:
NSString getPhone = [[NSUserDefaults standardUserDefaults] objectForKey:#"phoneNumber"];
NSLog(#"%#",getPhone);
hm, strange issue. you can print out getPhone directly after set user defaults to understand if some other part of code does not modify it. [[NSUserDefaults standardUserDefaults] setObject:myPhoneString forKey:#"phoneNumber"];
So try this:
NSLog(#"%#", myPhoneString); // check current value
[[NSUserDefaults standardUserDefaults] setObject:myPhoneString forKey:#"phoneNumber"];
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] objectForKey:#"phoneNumber"]) // check value after set it.
values should be the same, but also you will need to print this value in another place to test if some other code have not modified it. (I mean in place where you print it NSLog(#"%#",getPhone);)
Alos be sure that you set NSString to the NSUserDefault instead of data because as I see in your example you set NSString and output NSString as well so you don't need NSData in this your case.
NSString * getPhone = [[NSUserDefaults standardUserDefaults]
stringForKey:#"phoneNumber"];

iOS app crashing with error: NSCFNumber stringByReplacingOccurrencesOfString:withString: unrecognized selector sent to instance

Our iOS app terminates with an error of [__NSCFNumber stringByReplacingOccurrencesOfString:withString:]: unrecognized selector sent to instance 0x1755e090.
We're testing on an iPhone 5 w iOS 7.
It crashes on this line: [self parseDictionary:notificationMessage intoJSON:jsonStr].
Method containing this line:
- (void)notificationReceived {
NSLog(#"Notification received");
if (notificationMessage && self.callback)
{
NSMutableString *jsonStr = [NSMutableString stringWithString:#"{"];
[self parseDictionary:notificationMessage intoJSON:jsonStr];
if (isInline)
{
[jsonStr appendFormat:#"foreground:\"%d\"", 1];
isInline = NO;
}
else
[jsonStr appendFormat:#"foreground:\"%d\"", 0];
[jsonStr appendString:#"}"];
NSLog(#"Msg: %#", jsonStr);
NSString * jsCallBack = [NSString stringWithFormat:#"%#(%#);", self.callback, jsonStr];
[self.webView stringByEvaluatingJavaScriptFromString:jsCallBack];
self.notificationMessage = nil;
}
}
-(void)parseDictionary:(NSDictionary *)inDictionary intoJSON:(NSMutableString *)jsonString
{
NSArray *keys = [inDictionary allKeys];
NSString *key;
for (key in keys)
{
id thisObject = [inDictionary objectForKey:key];
if ([thisObject isKindOfClass:[NSDictionary class]])
[self parseDictionary:thisObject intoJSON:jsonString];
else
[jsonString appendFormat:#"\"%#\":\"%#\",",
key,
[[[[inDictionary objectForKey:key]
stringByReplacingOccurrencesOfString:#"\\" withString:#"\\\\"]
stringByReplacingOccurrencesOfString:#"\"" withString:#"\\\""]
stringByReplacingOccurrencesOfString:#"\n" withString:#"\\n"]];
}
}
Stack trace (along with one debugging line to show the variable value):
2014-01-07 16:32:36.980 Wopple[195:60b] Notification received
Printing description of self->notificationMessage:
{
"_" = "gHf8EeO3_ZDiugJkgA";
aps = {
alert = "hi foo bar right";
badge = 3;
};
}
2014-01-07 16:33:22.774 Wopple[195:60b] -[__NSCFNumber stringByReplacingOccurrencesOfString:withString:]: unrecognized selector sent to instance 0x1755e090
2014-01-07 16:33:22.776 Wopple[195:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber stringByReplacingOccurrencesOfString:withString:]: unrecognized selector sent to instance 0x1755e090'
*** First throw call stack:
(0x308c3e83 0x3ac246c7 0x308c77b7 0x308c60af 0x30814dc8 0x88da5 0x88d1f 0x88915 0x8757b 0x3335ec93 0x3335f75d 0x340d0b37 0x3088e777 0x3088e713 0x3088cedf 0x307f7471 0x307f7253 0x3552b2eb 0x330ac845 0x7f5d3 0x3b11dab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
When you're using:
[[[[inDictionary objectForKey:key]
stringByReplacingOccurrencesOfString:#"\\" withString:#"\\\\"]
stringByReplacingOccurrencesOfString:#"\"" withString:#"\\\""]
stringByReplacingOccurrencesOfString:#"\n" withString:#"\\n"]];
You're assuming that objectForKey is going to return an NSString object. But, in the case where your app is crashing, the object returned is actually an NSNumber.
You should use isKindOfClass: to determine the object type, or use stringValue on your NSNumber to get a string representation of the object.

Modifying NSDictionary in run Time [duplicate]

This question already has answers here:
Mutable Objects inside NSUserDefaults
(4 answers)
Closed 9 years ago.
Please Help me.
I have a plist clothingList.plist
I am accessing it like this in a method
NSString *path=[[NSBundle mainBundle] pathForResource:#"ClothingList" ofType:#"plist"];
//NSDictionary *ClothingAssets ; //Declared globally in .h file
ClothingAssets=[[NSMutableDictionary alloc]initWithContentsOfFile:path];
[[NSUserDefaults standardUserDefaults]setObject:ClothingAssets forKey:#"ClothingAssets"];
[[NSUserDefaults standardUserDefaults] synchronize];
Now I want to modfify a bool value in Clothing Assets Dictionary in another method.
ClothingAssets=[[NSUserDefaults standardUserDefaults] dictionaryForKey:#"ClothingAssets"];
[[[[[[ClothingAssets objectForKey:#"ClothingStore"] objectAtIndex:temp_Store]objectForKey:#"Assets" ]objectForKey:[NSString stringWithFormat:#"%#",temp_AssetType]] objectAtIndex:ii] setValue:#"YES" forKey:#"isLock"] ;
When I run the code For the first time it crashes and Show an error like this:
************ Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'***
*** First throw call stack:
(0x1fb5012 0x29c5e7e 0x1fb4deb 0x1f7b347 0x3f39bf 0x435d9 0x41f76 0xea5020 0x29d9705 0xab5920 0xab58b8 0xb76671 0xb76bcf 0xb75d38 0xae533f 0xae5552 0xac33aa 0xab4cf8 0x3397df9 0x3397ad0 0x1f2abf5 0x1f2a962 0x1f5bbb6 0x1f5af44 0x1f5ae1b 0x33967e3 0x3396668 0xab265c 0x22ed 0x2225 0x1)
libc++abi.dylib: terminate called throwing an exception******
But When I run the code for second time it is working properly.
please help me.
There are many similar questions. From the exception its evident that you are trying to include a value to an immutable dictionary.
Unwrap the values one at a time and since you are going to edit them always make a mutableCopy
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *clothingAssets=[[defaults dictionaryForKey:#"ClothingAssets"] mutableCopy];
NSMutableArray *clothingStores = [clothingAssets[#"ClothingStore"] mutableCopy];
NSMutableDictionary *clothingStore = [clothingStores[temp_Store] mutableCopy];
NSMutableDictionary *assets = [clothingStore[#"Assets"]mutableCopy];
NSString *assetTypesKey = [NSString stringWithFormat:#"%#",temp_AssetType];
NSMutableArray *assetTypes = [assets[assetTypesKey]mutableCopy];
NSMutableDictionary *assetType = [assetTypes[i] mutableCopy];
//Value is set
assetType[#"isLock"] = #"YES";
//Now you need to update the values back to the top most level
[assetTypes replaceObjectAtIndex:i withObject:assetType];
assets[assetTypesKey] = assetTypes ;
clothingStore[#"Assets"] = assets;
[clothingStores replaceObjectAtIndex:temp_Store withObject:clothingStore];
clothingAssets[#"ClothingStore"] = clothingStores;
[defaults setObject:clothingAssets forKey:#"ClothingAssets"];
[defaults synchronize];
Nested message sends aside, this is actually rather straightforward. When you see that error, it means you're trying to mutate an immutable object. The runtime throws a tantrum when you try to do that. Instead, do this:
ClothingAssets=[[NSUserDefaults standardUserDefaults] dictionaryForKey:#"ClothingAssets"];
NSDictionary *clothingStore = [ClothingAssets objectForKey:#"ClothingStore"];
NSArray *assets = [clothingStore objectForKey:#"Assets"];
NSDictionary *subAsset = [assets objectAtIndex: temp_Store];
NSArray *subAssetArray = [subAsset objectForKey: [NSString stringWithFormat:#"%#",temp_AssetType];
// At this point I'm afraid I run out of creative ways to describe your storage hierarchy:
NSDictionary *subAssetArraySubDictionary = [subAssetArray objectAtIndex: ii];
NSMutableDictionary *mutableCopy = [subAssetArraySubDictionary mutableCopy];
// And finally, set the value:
// Beware: This uses the string YES instead of a boolean value for YES - you need to remember this
// when accessing it later.
[mutableCopy setValue: #"YES" forKey: #"isLock"];

JSON Objective-C Parsing Fail

I have written the following code but I keep on getting nil. I have tried many different variations of this but I am failing exceptionally hard.
This is what I am getting from the server.
Two objects.
[{"description":"yolo.","name":"ye","id":1},{"description":"sMITH","name":"John","id":2}]
Any help would be greatly appreciated...... Thanks.
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
SBJsonParser *jsonParser = [[SBJsonParser alloc] init];
NSArray *jsonObjects = [jsonParser objectWithData:response];
NSMutableString *yolo = [[NSMutableString alloc] init];
for ( int i = 0; i < [jsonObjects count]; i++ ) {
NSDictionary *jsonDict = [jsonObjects objectAtIndex:i];
NSString *IDID = [jsonDict objectForKey:#"id"];
NSString *name = [jsonDict objectForKey:#"name"];
NSLog(#"ID: %#", IDID); // THIS DISPLAYS
[yolo appendString: IDID]; // THIS seems to be causing the new error...
[yolo appendString:#": "];
[yolo appendString: name];
NSLog(#"%#", yolo); // RETURNS NIL
}
EDIT:
currently my new error is...
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[NSDecimalNumber length]:
unrecognized selector sent to instance 0x81b89f0'
Looks like your [jsonDict objectForKey:#"id"] is an NSNumber(or NSDecimalNumber) and not an NSString. You should change the line NSString *IDID = [jsonDict objectForKey:#"id"]; to,
id myObject = [jsonDict objectForKey:#"id"];
NSString *IDID = nil;
if ([myObject isKindOfClass:[NSNumber class]]) {
IDID = [[jsonDict objectForKey:#"id"] stringValue];
} else {
IDID = [jsonDict objectForKey:#"id"];
}
This error appeared now since earlier you were not initializing NSMutableString *yolo and you were using appendString: on a nil object. Since now it is initialized as NSMutableString *yolo = [[NSMutableString alloc] init]; it is trying to call appendString on NSMutableString object which accepts only NSString type as its inputs where as you are passing an NSNumber in it. length is a method which appendString: internally calls. So you need to change this as well.
You never initialize yolo, so it's just nil the whole time you're calling -appendString: on it. Try this:
NSMutableString *yolo = [NSMutableString string];
Have you tried initializing the NSMutableString?
NSMutableString *yolo = [[NSMutableString alloc] init];
It looks like you are not really checking the type of the data coming to your app via your JSON feed. This might be the case of random crashes when users actually use your app. It might be also a reason for rejection to the App Store, is such crashes happen during your App's review.
You should be checking the type of all objects you receive from JSON, before calling methods on them :)
By implementing best practices you will have a stable and usable app. Build data models to validate your data. You can also you a JSON data model framework like JSONModel: http://www.jsonmodel.com/
It's obvious from your data that "id" is not a string, but a number. Assigning a pointer to an NSString* doesn't magically convert it to an NSString*. And it's obvious from the exception that you got that some object is an NSDecimalNumber when you thought it would be an NSString.
So: IDID is an NSNumber*, and pretending it is an NSString* will lead to crashes.

Get Row from NSArray

Hello i get a json that looks like this:
features: (
{
attributes = {
Gecontroleerd = Ja;
};
geometry = {
x = "5.968097965285907";
y = "52.50707112779077";
};
}
)
From this code:
NSDictionary *root = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSArray *data = [root objectForKey:#"features"];
NSLog(#"features: %#", data );
for (NSArray *row in data) {
NSString *latitude = row[5];
NSString *longitude = row[7];
NSString *crimeDescription = #"test";
NSString *address = #"banaan";
And u need to x values 5.968097965285907 for latitude
and y values 52.50707112779077 for longitude
But i get this error:
[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x14831450
2012-11-14 10:10:59.000 ArrestPlotter[6330:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x14831450'
*** First throw call stack:
(0x1860012 0x1655e7e 0x18eb4bd 0x184fbbc 0x184f94e 0x2dbc 0x3b8f 0x1cc1e 0x16696b0 0xfa0035 0x17e3f3f 0x17e396f 0x1806734 0x1805f44 0x1805e1b 0x224a7e3 0x224a668 0x4a765c 0x25bd 0x24e5 0x1)
libc++abi.dylib: terminate called throwing an exception
(lldb)
Does anyone wich row i need to select?
I guess that the only thing is that the row number needs to be changed. Or maybe there should be something like this : [1][5]. Im not quite sure how this works
NSArray *data = [root objectForKey:#"features"];
NSLog(#"features: %#", data );
for (NSDictionary *dic in data) {
NSDictionary geometry = [dic objectForKey:#"geometry"];
// Do what you want..
NSString *myAwesomeX = [geometry objectForKey:#"x"];
NSString *myAwesomeY = [geometry objectForKey:#"y"];
}
The problem here is that you are trying to send a selector message to object row, that is in memory a NSDictionary (NSCFDictionary?) object, and you are trying to manage it like a NSArray.
The method objectAtIndexedSubscript (is underlying called by row[5] and row[7]) exists in NSDictionary, but no in NSArray.
Change
for (NSArray *row in data) {
by
for (NSDictionary *row in data) {
Also, you have to change the management of data inside for, look at the result of your log statement and act accord whit it.
I hope this will help!

Resources