IOS/Objective-C: Get Number from JSON - ios

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

Related

Why is the value changing when I cast an int to an NSInteger?

I have an NSDictionary, and I perform objectForKey for key resource_type_id:
NSInteger resourceTypeID = [self.selectedDictionary objectForKey:#"resource_type_id"];
When I print resourceTypeID in the console, it returns 2 (the correct ID).
Now, I need to convert this NSInteger to an int to feed into my switch case statement.
Here is that code:
self.resourceTypeLabel.text = [ResourceType getResourceTypeFromResourceTypeID:(int)resourceTypeID];
However, when I do this, self.resourceTypeLabel.text returns nil.
Upon further inspection, when printing (int)resourceTypeID in the console, it returns 35.
Why is the number changing when I cast it?
-objectForKey: should return an object of type id, not an int. How are you setting the value?

Determine if NSUInteger has a value or is nil

I'm trying to use a HKAnchoredObjectQuery on iOS.
To do so I have to provide an anchor to the query which in this case is a NSUInteger. I want to save this integer for queries in the future in the NSUserDefaults and just simply want to use
if(anchor != nil) {
// do stuff
}
But the complier tells me that I'm not allowed to do this because I'm comparing a integer to a pointer and I understand why I'm not able to do this but I don't know how to do it.
The error code is this
Comparison between pointer and integer ('NSUInteger' (aka 'unsigned long') and 'void *')
Does anyone know how I'm able to determine if my anchor has a value or not?
NSUInteger is a primitive type, not an object type. NSNumber is an object type. For an NSNumber object, you can check whether it is nil or not. An NSUInteger is never nil because it is an integer, not a pointer.
Many functions that return NSUInteger as a result for a search return the constant NSNotFound if the search failed. NSNotFound is defined as a very large integer (2^31 - 1 for 32 bit, 2^63 - 1) for 64 bit).
NSUInteger is not an object and cannot be compared to nil. In over-simplistic terms, an object is a pointer to a memory location that may contain an value or be nil. NSUInteger is just a value. It may be 0, or some other value that you don't expect, but it will have a value.
An NSUInteger cannot be nil because it is not an object. The default value on creation would be zero. To save in NSUserDefaults, you could store it as an NSNumber, which could be checked for nil later.
To store it in NSUserDefaults:
NSNumber *aNumber = #(anchor);
[[NSUserDefaults standardUserDefaults] setObject:aNumber forKey:aKey];
To get the anchor back from NSUserDefaults:
NSNumber *aNumber = [[NSUserDefaults standardUserDefaults] objectForKey:aKey];
if (aNumber != nil) {
NSUInteger anchor = [aNumber integerValue];
}
NSUInteger or simply int are basically primitive data types and they should be compared with the integer values with in the range of the corresponding data types. nil is used with referenced objects.
In your case, as anchor is NSUInteger so you should use integer value for comparison in place of nil as-
if(anchor != 0) {
// do stuff
}

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.

How do I use a core data Integer 64 property?

I want to have an Entity property in Core Data be a 64-bit integer. Since the model is going to run on iOS, and as far as I know these devices are not 64-bit, I figured that NSNumber was the way to go (core data gives you the option of objects or scalar properties for primitive types).
I'm assuming that NSNumber will internally take care of keeping track of a suitable representation for 64 bits.
Now, I need to subtract 1 from this "64 bit" property in my entity at some point (in case you didn't guess, the 64 bit property is the max_id parameter in the Twitter API), but to do so, I first need to unbox the number inside the NSNumber property.
So should i get the intValue? longValue? unsignedIntValue? unsignedLongValue? long long? which one?
Since you already know the type (64 bit integer), you don't need to check for it.
To get a 64 bit integer out of a NSNumber, do one of the following:
NSInteger myInteger = [myNSNumber integerValue];
int64_t myInteger = [myNSNumber integerValue];
In order to just add one to it, you can use something like this:
myNSNumber = [NSNumber numberWithInteger:[myNSNumber integerValue]+1]];
Note that iOS does have 64 bit data types like int64_t and NSInteger.
EDIT:
If the only reason that you are using NSNumber is to store the 64 bit integer, you can just declare the property like this in your model subclass and skip the unboxing/boxing altogether:
#property (nonatomic) int64_t myIntValue;
Note that core data does this by default if you select the Use scalar properties for primitive data types option of the Create NSManagedObject Subclass feature.
Try putting this in a NSNumber category:
-(int64_t) int64value
{
if (sizeof(short) == 8)
return [self shortValue];
if (sizeof(int) == 8)
return [self intValue];
if (sizeof(long) == 8)
return [self longValue];
if (sizeof(long long) == 8)
return [self longLongValue];
return -1; // or throw an exception
}
To get the C type contained in NSNumber use objCType
Example
NSNumber *myFloat = [NSNumber numberWithFloat:5.5f];
NSLog(#"%s", [myFloat objCType]);
Will print "f" as it contains a value of type float.
Also, check out #encode() which will return a C type character.
Example
NSNumber *myFloat = [NSNumber numberWithFloat:5.5f];
if (strcmp(myFloat) == #encode(float)) {
NSLog(#"This is a float");
}
Also
NSNumber *myFloat = [NSNumber numberWithFloat:5.5f];
CFNumberType numberType = CFNumberGetType((CFNumberRef)myFloat);

Resources