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

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.

Related

NSMutableDictionary returning null

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).

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];

Xcode, ios, Set name of variable to value of another variable?

I want to set the name of a variable to the value of another variable are there any other ways to do this because I don't think this is the way.
NSString *myint = #"a";
NSString *([NSString stringWithFormat:#"%#", myint]) = #"something";
NSLog(#"%#", a);
No, you can't do that. Once your code is compiled, your variables don't really have names -- just locations. The names you see in the debugger are provided by a symbol file which the debugger uses to map locations to names.
Key-value coding could help, depending on what you're really trying to accomplish. With KVC, you use key names to refer to values rather than accessing variables, much as you do with a dictionary. For example, if you have an object with properties foo and bar, you can then do something like this:
NSString *key = #"foo";
[myObject setValue:#(5) forKey:key];
You could even override -setValue:forKey: so that it accepts any key and remembers the value (which is exactly what a dictionary does).
You can go in the other direction (set a variable to the name of another variable) using the stringification operator, but it's kinda hacky and not usually all that useful. In a nutshell, macro parameters prefixed with a # are used as literal strings instead of being evaluated. So you'd create a macro like this:
#define string(x) #x
and then you'd use it somewhere in your code like this:
int foo = 5;
NSLog("The name of the variable is %s and its value is %d.", string(foo), foo);
with the following result:
The name of the variable is foo and its value is 5.
I agree with Paulw11. You could define a NSMutableDictionary to hold all your variables by key. I don't think there is any way the compiler can use a handle determined at runtime. But you can achieve the same affect.
So say, for instance, that both the variable handle and value were NSString, then you could do something like this.
NSMutableDictionary *myObjects = [[NSMutableDictionary dictionary] init];
NSString variableName = #"myString";
[myObjects setObject #"Variable value" forKey: variableName];
NSLog("Variable %# has value %#.", variableName, [myObjects objectForKey: variableName]);

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];

adding Char or NSString into Objective C enum

I have created an enum in my header file that looks like this
typedef enum {stTMD = 1, stT2MD = 2, stDCMD = 'D', stMBMD = 'M'} stTypes;
First off I am not even sure if thats the correct way to declare a char in an enum but
As you can see some values are integers and others are chars. However I am getting the following error when I try to place these values into a NSDicitonary like this
NSDictionary *iCTypes = [[NSDictionary alloc] initWithObjectsAndKeys:stDCMD,#"stMB", stMBMD,#"stMBMD", nil];
but I am getting this error below
Implicit conversion of 'int' to 'id' is disallowed with ARC
any help would be greatly appreciated.
An enum is basically an int type. Your enum definition is just fine. The problem is your use in the dictionary. You need to wrap the enum values in an NSNumber.
Try:
NSDictionary *iCTypes = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInt:stDCMD], #"stMB", [NSNumber numberWithInt:stMBMD] ,#"stMBMD", nil];
or even better (using modern Objective-C):
NSDictionary *icTypes = #{ #(stDCMD) : #"stMB", #(stMBMD) : #"stMBMD" };
You need to store objects inside it, so you can't store an int, rather a NSNumber, which can be made by appending a # before the number constant:
NSDictionary *iCTypes = [[NSDictionary alloc] initWithObjectsAndKeys: #(stDCMD),#"stMB", #(stMBMD),#"stMBMD", nil];
However a clarification is needed on this:
First off I am not even sure if thats the correct way to declare a char in an enum but As you can see some values are integers and others are chars.
When you define an enum it stores integers, it doesn't matter if you set chars as values, they're compatible with int so the compiler will not complain. But the storage type is the same, they're still integers and any type compatible with integers will be accepted.
Both the objects and keys in an NSDictionary must be objects, and the keys specifically must be objects that conform to NSCopying. In order to use ints in an NSDictionary, you have to convert them to NSNumbers. You can use either [NSNumber numberWithInt:stDCMD] or, if you're using a newer version of Xcode, #(stDCMD).
In C char is a kind of short int.
enum can only hold integer types.
NSDictionary cannot hold C types. Only objects.
You can wrap your C types in NSValue or NSNumber to put in an NSDictionary.

Resources