NSMutableDictionary returning null - ios

I created an NSMutableDictionary in NSObject class like
#property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSString *> *requestComments;
and saved the data in this variable when comes through API.
But when I am sending the key to get the value it is returning null every time.
To get the value I am doing like this
NSLog(#"%#",dataManager.requestComments[serviceRequest.RequestId]);
// serviceRequest.RequestId is returning NSNumber.
the output I'm getting is "(null)"
if I use to like this then it returns a value
NSLog(#"%#",[dataManager.requestComments valueForKey:#"30221"]);
Why it is returning null in the above case.

Based on your question, this should work
NSLog(#"%#",dataManager.requestComments[[serviceRequest.RequestId stringValue]]);
Because you gave the key as NSString and you are expecting it to return based on an NSNumber. You need to look at the code which you are using to store this dictionary.
Update
You have mentioned that key is of NSNumber type. But you are passing a string in valueForKey and getting a valid object back. You should check how you are forming this dictionary from API response.

Because you declared requestComment to be aNSDictionary which keys are NSNumbers and values are NSString doesn't oblige it to respect it.
Sample:
_requestComments = [[NSMutableDictionary alloc] init];
[_requestComments setObject:[NSNumber numberWithInt:34] forKey:#"54"]; // => Warning: Incompatible pointer types sending 'NSNumber * _Nonnull' to parameter of type 'NSString * _Nonnull'
id obj = [NSNumber numberWithInt:35];
id key = #"55";
[_requestComments setObject:obj forKey:key];
NSLog(#"[_requestComments objectForKey:#\"55\"]: %#", [_requestComments objectForKey:#"55"]); //Warning: Incompatible pointer types sending 'NSString *' to parameter of type 'NSNumber * _Nonnull'
NSLog(#"[_requestComments objectForKey:#(55)]: %#", [_requestComments objectForKey:#(55)]);
Logs:
$>[_requestComments objectForKey:#"55"]: 35
$>[_requestComments objectForKey:#(55)]: (null)
Okay, I used id to lure the compiler, but id is a common returned "class", in objectAtIndex:, etc. It's common in JSON parsing when you think a object will be a NSString but is in fact a NSNumber of (inverse).
Before doing requestComments[serviceRequest.RequestId], enumerate ALL the keys value & class and ALL objects value & class. You can check it like this:
for (id aKey in _requestComments)
{
id aValue = _requestComments[aKey];
NSLog(#"aKey %# of class %#\naValue %# of class %#", aKey, NSStringFromClass([aKey class]),aValue, NSStringFromClass([aValue class]));
}
Then you can try to track where you put a wrong key (class).

Related

JsonModel NSString transform null to empty string

I am using JSONModel in my application. Is it possible to prepare category with JSONValueTransformer that will transform nil/null NSString to empty string (#""). So far when property in json response is null, my property in object becomes #"".
Because the whole API is not very well (it's external) I would like to avoid overriding initWithDictionary in every object and use just ValueTransformer for every JSONModel class with NSString property and map it to correct string or empty string if nil/null.
After getting response, run following loop with your response dictionary and its key.
for (id dictionary in [[responseDictionary valueForKey:#"responseKey"] allKeys] )
{
([[responseDictionary valueForKey:#"responseKey"] valueForKey:dictionary] == [NSNull null]) ? [[responseDictionary valueForKey:#"responseKey"] setValue:#"" forKey:dictionary] :[[responseDictionary valueForKey:#"responseKey"] setValue:[[responseDictionary valueForKey:#"responseKey"] valueForKey:dictionary] forKey:dictionary];
}

IOS/Objective-C: Get Number from JSON

I have a JSON dictionary that contains what I will call an integer (in mathematics) i.e. 1.
I would like to save this number to a core data attribute that is an NSInteger. The following code is issuing warning:
Incompatible Pointer to Integer Conversion initializing NSInteger with an expression of type 'id'
NSInteger insertID = jsonResults[#"insert_id"];
I have tried various combinations of int, NSNumber, etc. to no avail. Can anyone suggest right way to do this?
NSDictionary can't store NSInteger. It is storing NSNumber. So you need to unwrap the NSNumber:
NSInteger insertID = [jsonResults[#"insert_id"] integerValue];
in core data you should save numeric value as Number Type.
For eaxample,
To save:
insert_id = #(100)//say 100 is your insert_id value
To read:
NSInteger insertID = [jsonResults[#"insert_id"] intValue];

iOS converting value in NSDictionary with (int) fail

I had a NSDictionary contains 2 key/value pairs:
NSDictionary *dic = #{#"tag":#2, //NSNumber
#"string":#"someString"}; //NSString
NSLog(#"%i",(int)[dic objectForKey:#"tag"]); //print out 34
NSLog(#"%i",[dic objectForKey:#"tag"] intValue]); //print out 2
Why does "converting id value to int with (int)"get me the wrong result but not the other way? are they in different levels of conversion?
Why does "converting id value to int with (int)"get me the wrong result but not the other way? are they in different levels of conversion?
id is a pointer type. id pointers point to Objective-C objects in memory. By casting id to (int), you are merely reinterpreting (some of) the pointer's bit pattern as an int, which is quite meaningless. You have to call the proper conversion methods of NSString and NSNumber if you want to reliably get the primitive values out of the Objective-C object.
If you ever seemingly get the "correct" value of 2 in the case of pointer-casting with NSNumber, that may be because the Objective-C runtime makes use of an optimization technique called tagged pointers, whereby small objects are not really created and allocated, but their semantics (the number's bits which the NSNumber object stores) is stuffed into the unused bits of the pointer.
#2 is not an int but a NSNumber you can't cast an NSNumber into an int. You have to use intValue method to get the correct result.
The method objectForKey: returns a pointer to the NSNumber object #2, not the value stored in the object itself. So you're typecasting the pointer, not the value 2. In the last line you don't typecast the object but you access a property called intValue which returns the value of the object expressed as an int.
NSDictionary contains Object with Key value pairs,but you passed int(#2) into object
NSDictionary *dic = #{#"tag":#2, //NSNumber
#"string":#"someString"};
so Change int to NSNumber like
NSDictionary *dic = #{#"tag":[NSNumber numberWithInt:2];,#"string":#"someString"};
and you can get it..
int number = [[dict objectForKey:#"tag"] intValue];

#encoding for type id where id is actually any object

I have a following method.
- (void)someObject:(id)obj {
char* encoding = #encoding(typeof(obj));
NSString *s = [NSString stringWithCString:encoding encoding:NSUTF8StringEncoding];
NSLog(s);
}
this method always return #"#" whether I pass a variable of type NSNumber, NSArray, NSDictionary or NSString in obj. I assume it is checking the obj pointer type.
What do I have to do so that it returns the actual type encoding of the variable that I have passed?
#encode() is a compile-time construct; it only knows about the variable's type, not the class of the object that will be contained in the object at runtime. Any object-typed variable will encode to #.
You will have to use runtime checks, asking the objects for their classes, to accomplish your goal.

iOS: NSUserDefaults Warning When I Try to Insert an "int" Value

In my app I wish to save at some point an "int" value in NSUserDefaults, and it gives me warning about the value not being of an "id" type and being an "int". i don't get this warning if I try to insert an NSString.
Here are the details.
The code I have written:
int currentCategoryForUserDefaults = currentCategory; //"cuurentCategory" is an enum value.
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:currentCategoryForUserDefaults forKey:#"currentCategoryForUserDefaults"];
The warning I get (for the 3rd line):
Semantic Issue : Incompatible integer to pointer conversion sending 'int' to parameter of type 'id'
Anyone?
Use setInteger:forKey: instead of setObject:forKey:. An integer is not an object, it's a primitive type.
Then, you can retrieve it with integerForKey:.
Another option is to wrap your integer into a NSNumber object.
Try use - (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName instead or wrap your int value into NSNumber and this will be exactly what debugger wants from you.

Resources