I'm reading through some source code and I noticed the following API, where the developer passes in nil if they want an object to be removed.
- (void)setSomeStatus:(SomeStatusObject *)status {
if (status != nil) {
[store setObject:status forKey:SOME_STATUS_KEY];
} else {
[store removeObjectForKey:SOME_STATUS_KEY];
}
}
My specific question is if the above can be reduced to
- (void)setSomeStatus:(SomeStatusObject *)status {
[store setObject:status forKey:SOME_STATUS_KEY];
}
Or alternatively
- (void)setSomeStatus:(SomeStatusObject *)status {
store[SOME_STATUS_KEY] = status;
}
No, they are not equivalent. In fact, passing nil to setObject:forKey: (either the value or the key) will result in a runtime exception.
You can't set a value to nil using setObject:forKey.
NSDictionary wants an object, even if that object represents NULL, and the value alone can't be set to simply nil. (You could set it to NSNULL though).
So to answer your question, your code can't replace the existing.
Related
Is there a way to loop through nsdictionary in objective C where key values are not known and the dictionary is deeply nested. Can anyone please help? i searched a lot couldn't find a definitive solution for this.
I will get a JSON string which i am moving into a NSDictinary variable, here some values are encrypted some are not. I need to decrypt only certain parts of the json. I know which key value pair i need to decrypt. (which also is a part of the json string, i.e is available in the outer nest). But for each JSON response the string will change so i don't know where the encrypted key value pair will be. I just know the key name. So i need to loop through the entire json and find those key pairs to decrypt. Also the json is deeply nested.
Hi thanks for responding here is the sample json
This is a sample json (not the exact string)
{
"DTLS": [
{
“VALUE1”: “ASsddcFF12223fdvfvfvffrefcdcssss”
},
{
"VALUE2”: “sdsdd2323edffvfvb4ddcdccvvvrfdc”
},
{
"VALUE3”: "sdsdd2323edffvfvb4ddcdccvvvrfdc"
},
],
"Decryptkeys":"VALUE1|VALUE2|VALUE3"
"isSuccessful": true,
"responseTime": 2014,
"totalTime": 2014,
"responseCode": "S",
"statusCode": 200
}
The above response may change in the another server call where DTLS could be nested inside another json key like MAINDTLS, so the only key that i can blindly take is Decryptkeys. I know where this will be. But the ones inside Decryptkeys i.e VALUE1,VALUE2,VALUE3 maybe nested somewhere deep inside the json.
Check this answer:
how to iterate nested dictionaries in objective-c iphone sdk
https://stackoverflow.com/a/40942013/2432053
EDIT
Here is modified version:
- (id)findflat:(NSString *)keyToFind {
if([self objectForKey:keyToFind]) {
return self[keyToFind];
}
for(id key in self.allKeys) {
if ([self[key] isKindOfClass:[NSArray class]]) {
for (id obj in self[key]) {
if ([obj isKindOfClass:[NSDictionary class]]) {
id res = [obj findflat:keyToFind];
if (res) {
return res;
}
}
}
}
}
return nil;
}
First two if conditions check if value is kind of dictionary or array if so it has to be parsed.
Last if condition if ([self respondsToSelector:NSSelectorFromString(key)])
This is where you get value.
In my case I have a custom NSObject, what I'm doing here is checking if this object respond to particular key then I'm setting the value...
In your case i believe last if condition should check if key is DTLS...then do your stuff
Hope this helps...
-(void)parseDictionary:(NSDictionary*)dict{
for (NSString *key in dict) {
if([[dict valueForKey:key] isKindOfClass:[NSDictionary class]]){
[self parseDictionary:[dict valueForKey:key]];
}else if([[dict valueForKey:key] isKindOfClass:[NSArray class]]){
for (NSDictionary* object in [dict valueForKey:key]) {
[self parseDictionary:object];
}
}else if ([self respondsToSelector:NSSelectorFromString(key)]) {
[self setValue:[dict valueForKey:key] forKey:key];
}
}
}
I have my coredata set up and saving and fetchRequests work well. In this case I am fetching the first object saved in 'Item' but if the fetchResult is empty I do not want to call my method 'displayDataInLabel' as if there is nothing in it this method breaks (i'm guessing because the is nothing at 'objectAtIndex:0'
-(void)viewDidAppear:(BOOL)animated
{
if (_fetchResultsController.fetchedObjects == nil) {
return;
}
else
[self displayDataInLabel];
}
-(void)displayDataInLabel
{
Item *thisItem = [_fetchResultsController.fetchedObjects objectAtIndex:0];
NSLog(#"test item %#", thisItem.name);
}
It is not sufficient to check for nil because the result, even if nothing is found, will still be a valid (empty) array, which is not nil.
Instead, check if the count property of the result is zero.
i'm making an iOS app using VKSdk.
I want to copy data from response.json[#"items"](it's nsarray,response.json its nsdictionary) to my nsarray.
Here is my code:
VKRequest * getWall = [VKRequest requestWithMethod:#"wall.get" andParameters:#{VK_API_OWNER_ID : #"1"} andHttpMethod:#"GET"];
[getWall executeWithResultBlock:^(VKResponse * response) {
_vk_array=[[NSArray alloc]initWithArray:response.json[#"items"]];
NSLog(#"%#",_vk_array);//shows null
NSLog(#"%#",response.json[#"items"]);//shows ok
} errorBlock:^(NSError * error) {
if (error.code != VK_API_ERROR) {
[error.vkError.request repeat];
}
else {
NSLog(#"VK error: %#", error);
}
}];
I also trying to use just this code
_vk_array=response.json[#"items"]
But it still shows "null". Am i doing something wrong?
PS:
NSLog(#"%hhd",([response.json[#"items"] isKindOfClass:[NSArray class]]));//shows 1
Hi you can use it to copy an array object into another array.
NSArray *copyArray = [NSArray arrayWithArray:yourArray];
Thanks
[response.json[#"items"
_vk_array=[[NSArray alloc]initWithArray:response.json[#"items"]];
NSLog(#"%#",_vk_feed);//shows null
here you are assigning value to _vk_array But you are tracing value of _vk_feed.
Also, [response.json[#"items" is incomplete.
I am getting a json document like this from a ws:
{
...
error=true,
errorMsg="xyz",
errorCode="1234"
}
But these attributes are optional so sometimes they are present and sometime they are not.
I added a dynamic mapping for reading only error - only if error is set to true
either:
[dynamicMapping addMatcher:[RKObjectMappingMatcher matcherWithKeyPath:#"error" expectedValue:[NSNumber numberWithInt:1] objectMapping:errorMapping]];
or
[dynamicMapping setObjectMappingForRepresentationBlock:^RKObjectMapping *(id representation) {
if ([[representation valueForKey:#"error"] isEqualToNumber:[NSNumber numberWithInt:1]]) {
return errorMapping;
}
return nil;
}];
Everything is working fine if error=true but if the error attributes are missing I get a warning:
restkit.object_mapping:RKMapperOperation.m:98 Adding mapping error: Could not find an object mapping for keyPath: '<null>'
I just want to get rid of the warning. What is the best practice for this problem? How do I mark the attribute as optional?
To remove the warning, you need to complete your mapping configuration, because currently you're only giving it information for half of the scenarios. The warning is just that, a warning. It may be that it is intended functionality, that's why it isn't an assertion.
So, you're handling the error situation, simply add another check, something like:
[dynamicMapping setObjectMappingForRepresentationBlock:^RKObjectMapping *(id representation) {
NSNumber *errorNumber = [representation valueForKey:#"error"];
if (errorNumber == nil) {
return successMapping;
} else if ([errorNumber isEqualToNumber:[NSNumber numberWithInt:1]]) {
return errorMapping;
}
return warningMapping;
}];
Also, you aren't limited to checking just the 'error' parameter. You can check any other key and value in the response, both for existence and for value.
I always use NSLog to print out contents of objects when I am debugging my iOS applications. But any time I come across a "nil" object, the program crashes. In Java, if an object is null, it will print "null". Is there a way to do this in Objective-C?
Something like:
if (questionableObject == nil) {
NSLog(#"questionableObject is nil.");
} else {
NSLog(#"questionableObject is: %#", questionableObject);
}
I've only really run into this problem when I send a message to an object inside the NSLog parameter list that uses a nil object as a parameter. Something like this:
if (questionableObject == nil) {
NSLog(#"questionableObject is nil.");
} else {
NSLog(#"result is: %#", [something someMessage:questionableObject]);
}
What do you mean by "print out contents of objects"? If you're dereferencing a nil pointer, that'll cause a problem. If you're just printing the pointer, that should be OK. You can also send messages to nil without problem, so you could do this:
NSLog(#"theObject is: %#", [theObject description]);