I'm facing issue that xcode showing me warning: Incompatible pointer to integer conversion sending 'id _Nullable' to parameter of type 'unsigned long long'
the line is:
NSDecimalNumber *amount_total = [NSDecimalNumber decimalNumberWithMantissa:indic[#"amount"] exponent:-2 isNegative:NO];
it complain of indic[#"amount"] and this is a value of amount came from React-Native. even if I console log this in xcode it showing me a number which is came right from RN.
any solution to avoid that, however the app also crash because of this.
Thanks
Foundation collections (including NSDictionary) store numbers as NSNumber objects. The error is informing you that it is expecting an unsigned long long, so you should use unsignedLongLongValue to extract that value from the NSNumber in your NSDictionary:
NSDecimalNumber *amount_total = [NSDecimalNumber decimalNumberWithMantissa:[indic[#"amount"] unsignedLongLongValue] exponent:-2 isNegative:NO];
See Most Collections Are Objects and Numbers Are Represented by Instances of the NSNumber Class.
Related
NOTE: Please fully read the problem before devoting it or closing it.
I have a dictionary packedData which has a value '1' in it of NSNumber type & of key "example". I save this value to core data as
myentity.attribute = [packedData valueForKey:#"example"]; //attribute is of NSNumber type as well.
when I fetch the data, the value returned is "23008" or some other unrelated value. I debugged it to find that it's a value conversion issue while saving it to core data.
Does anyone know why this occurs or its solution??
UPDATE: NSString and NSDate type are saved fine (exact values as in dictionary).
If you have "use scalar property" selected for an integer type property, the generated code is something like
#property (nonatomic) int16_t attribute;
If you uncheck that, the code looks like
#property (nullable, nonatomic, copy) NSNumber *attribute;
The first case is a raw integer type; the second one is an NSNumber object that Core Data will treat as containing an integer.
Your line of code looks like this:
myentity.attribute = [packedData valueForKey:#"example"];
The valueForKey call will return an object, in your case an NSNumber. But there's no automatic conversion between NSNumber and scalar types. So if you're using the scalar version you end up assigning the pointer value of the NSNumber. That is, you get the memory address of the NSNumber instead of the value it contains.
You can fix this either by
Not using the scalar type, so that you have an NSNumber everywhere.
Keeping the scalar type but then changing your line of code to convert the object to its integer value:
newEvent.attribute = [[packedData valueForKey:#"example"] integerValue];
The compiler should have warned you about this! I would have expected a warning reading something like incompatible pointer to integer conversion assigning to 'int16_t' (aka 'short') from 'id _Nullable'.
I am still fairly new to Objective-C and iOS development
. I am able to make an app run fine with core data when all the attributes are strings only. My problem occurs when i have an entity (i made a test one to show as an example) which has an attribute that is set to be of type integer 16(though i have tried setting both integer 16 and integer 64 and get the exact same errors) but i cannot seem to understand how i am supposed to convert the string input from a user to a format which will be accepted as a value to be set. I keep getting the same error messages (implicit conversion of NSInteger to IDNullable is disallowed in ARC) & (incompatible integer to pointer conversion sending NSInteger(AKA "long" to parameter of type ID Nullable)
ex 1:
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *newEntity = [NSEntityDescription insertNewObjectForEntityForName:#"TestEntity" inManagedObjectContext:context];
int valueOne = [self.valueOneIn.text intValue];
[newEntity setValue:valueOne forKey:#"value1"]; //!!2 errors listed above
ex 2 (above ex edited):
NSInteger valueOne = [self.valueOneIn.text intValue];
[newEntity setValue:valueOne forKey:#"value1"]; //!!2 errors listed above
ex 3 (ex1, just edited):
NSInteger *valueOne = [self.valueOneIn.text intValue]; //!!error
[newEntity setValue:valueOne forKey:#"value1"]; //!!2 errors listed above
I have attached two photos showing simple examples of the errors that i am getting. I have spent the past couple days looking up videos, online courses and even reading some possible solutions on stack overflow, but none seem to remedy the situation (my examples above were made in my attempts to use the potential solutions i had found but, most cover using core data and string values or NSDate values). Any help or nudge in the right direction would really (i cannot stress this enough, i mean really) be appreciated[example of error when setting to NSIntegerexample of error with NSInteger
The setValue:forKey: method wants an object as the value. But int and NSInteger are primitive numeric types, not objects. That's why the first two examples don't work. The third one doesn't work because a pointer to NSInteger is still not an object.
Assuming that valueOneIn is a text field, you should do something like:
NSInteger valueOne = [self.valueOneIn.text integerValue];
[newEntity setValue:#(valueOne) forKey:#"value1"];
The #(valueOne) syntax tells the compiler to convert the NSInteger variable valueOne to an instance of NSNumber. That's a class designed to wrap numeric values when objects are required, so it's what you need for setValue:forKey:. Also, note that the code uses integerValue instead of intValue-- which is better because the compiler will use the correct integer size depending on the platform you're targeting.
It would be better to use custom NSManagedObject subclasses for your entities than to use NSManagedObject directly. One major advantage is that setValue:forKey: will accept any object as the value. Subclasses will tell the compiler what object types are acceptable, so that the compiler can verify that you're using the correct types.
I am new to the iOS development and I was trying to do something mentioned below and it was giving me an error:
Implicit conversion of an objective c pointer to 'NSInteger*(aka int*) is disallowed with ARC.
In the below code, seg_pressed is a property of segmented control.
NSInteger *choice =[NSNumber numberWithInt:_seg_pressed.selectedSegmentIndex];
What am I doing wrong?
NSInteger is a raw type (much like C's "int" or "char"). You should declare "*choice" as a "NSNumber *" object.
E.G.:
NSNumber *choice = [NSNumber numberWithInt:_seg_pressed.selectedSegmentIndex];
NSNumber is an Objective-C object, whereas NSInteger ultimately turns into a "long". Which can be different depending on which platform/architecture you're running under. As Apple's Foundation data types doc says:
When building 32-bit applications, NSInteger is a 32-bit integer. A
64-bit application treats NSInteger as a 64-bit integer.
When I attempt to create an NSNumber using the numberWithLongLong with a number greater than -2 and less than 13 it returns a number that is casted as an (int).
I see this if I look at the Xcode debugger after stepping over my line.
NSNumber* numberA = [NSNumber numberWithLongLong:-2]; //Debugger shows as (long)-2
NSNumber* numberB = [NSNumber numberWithLongLong:-1]; //Debugger shows as (int)-1
NSNumber* numberC = [NSNumber numberWithLongLong:12]; //Debugger shows as (int)12
NSNumber* numberD = [NSNumber numberWithLongLong:13]; //Debugger shows as (long)13
To put my problem in context, I am using a long long value for an epoch date that I will end up serializing using BSON and sending across the wire to a webservice. The webservice requires the date to be a java Long.
Thanks in advance
You have discovered that NSNumber (actually, its CFNumber counterpart) has a cache for integers between -1 and 12 inclusive. Take a look at the CFNumberCreate function in CFNumber.c to see how it works.
It looks like you can force it not to use the cache by passing your own allocator to CFNumberCreate. You'll need to look at the CFAllocator documentation.
But note that the CFNumberCreate manual says this:
The theType parameter is not necessarily preserved when creating a new CFNumber object.
So even if you bypass the cache, you might not get back an object whose objCType is q (which means long long). It looks like the current implementation will return q but that could change in a future version.
You are allowed to write your own NSNumber subclass if you need to guarantee that objCType returns q. Read “Subclassing Notes” in the NSNumber Class Reference.
You can use your webservice without concern.
NSNumber wraps a numeric value (of primitive type) as an object. How NSNumber stores that value is not really your concern (but there is a method to find it out), it is an opaque type. However NSNumber does maintain an internal record of the type used to create it so its compare: method can follow C rules for comparison between values of different types precisely.
For integral types the integral value you get back will be exactly the same, in the mathematical sense, as the one you created the NSNumber with. You can create an NSNumber with a short and read its value back as a long long, and the mathematical value will be the same even though the representation is different.
So you can store your integral date value as an NSNumber and when you read it back as a long long you will get the right value. No need to be concerned how NSNumber represents it internally, and indeed that could potentially change in the future.
(At least one implementation of NSNumber can store values as 128-bit integers, which helps ensure correct semantics for signed and unsigned integers. Also I stressed integral types as with the vagaries of real numbers talking about mathematical exactness is somewhat moot.)
Wait. I think I know what your asking. Try it this way:
NSNumber* numberA = [NSNumber numberWithLongLong:-2LL];
NSNumber* numberB = [NSNumber numberWithLongLong:-1LL];
NSNumber* numberC = [NSNumber numberWithLongLong:12LL];
NSNumber* numberD = [NSNumber numberWithLongLong:13LL];
BTW: it won't matter what the type of the constant is, it will be coerced into a long long when passed to [NSNumber numberWithLongLong:]
UPDATE
Based on #robmayoff's answer, I don't think NSNumber is reliable for your. How are you packing your BSON? is there a way to use NSValue instead of NSNumber?
I'm a newbie in obj c. So I have a simple question.
I have a matrix of NSInteger values. It is called "curBoard". I want to update value at (x,y) coordinates with value "curStep". I have an arror "operand of type void where arithmetic..."
What am I doing wrong ?
[curBoard replaceObjectAtIndex:x withObject:(NSMutableArray *)[[curBoard objectAtIndex:x] replaceObjectAtIndex:y withObject:(NSInteger *)[NSNumber numberWithInt:curStep]]];
Update:
NSMutableArray *board;
board = [NSMutableArray new];
for(NSInteger i = 0; i<boardSize; i++) {
NSMutableArray *row = [NSMutableArray new];
for(NSInteger j = 0; j < boardSize; j++)
[row addObject:(NSInteger *)[NSNumber numberWithInt:0]];
[board addObject:row];
}
This withObject:(NSInteger *)[NSNumber numberWithInt:curStep]] part is what causing an issue. If you are storing as NSNumber objects, you should just use:
... withObject:[NSNumber numberWithInt:curStep]]
Edit:
From the code posted above, you should add it as:
[row addObject:[NSNumber numberWithInt:0]];
NSInteger is not of pointer type and you should use NSNumber itself to add to array.
Objective-C is basically just a bunch of object syntax strapped to C. The overall effect is something like strapping a jetpack to a horse: sometimes the two parts don't really work together very well. In this case, you're trying to go faster by telling the horse to giddy up, when you should really be opening up the throttle.
NSMutableArray is part of the jetpack—it's an Objective-C object and is only equipped to handle arrays of Objective-C objects. But NSInteger is part of the horse—it's a primitive C integer type, not a real object.*
I know NSInteger is capitalized like a class and has an NS prefix like a class, but it's really a creature of C. You can confirm this yourself—type Cmd-O in Xcode and type "NSInteger" into the Open Quickly dialog that pops up, and you'll be able to jump to its definition. In my current Mac project, that's typedef long NSInteger;; long is one of the primitive C types.
NSNumber exists to bridge the two. It's an object specifically designed to hold the C numeric types inside it. Since NSNumber is an object, NSMutableArray and other Objective-C things can deal with it.
But you can't just cast between NSNumber and NSInteger. NSNumber holds an NSInteger inside it, but that doesn't mean it's actually an NSInteger itself. If you put a sandwich in a plastic bag, you can't eat the bag.
Instead, you have to use NSNumber's +numberWithInteger: method to construct an NSNumber, and -integerValue to get the integer back out of it. (+numberWithInt: and -intValue will usually work, but they may behave differently with very large values, depending on whether your app is running on a 32-bit or 64-bit processor.) Actually, nowadays you can say [NSNumber numberWithInteger:foo] as #(foo) instead, which is a lot shorter.**
So when you add a number, you should be saying:
[row addObject:#(0)];
And when you later want that number back, you'll want to say something like:
n = [[row objectAtIndex:y] integerValue];
The -replaceObjectAtIndex:withObject: error is a different story. -replaceObjectAtIndex:withObject: doesn't return anything at all, so you can't use it as an argument. Luckily, you don't need to in this case. -replaceObjectAtIndex:withObject: doesn't create a new array; it alters the array that's already inside [curBoard objectAtIndex:x], so you don't need to do anything to curBoard. Instead, you can just write:
[[curBoard objectAtIndex:x] replaceObjectAtIndex:y withObject:#(curStep)];
* You actually used NSInteger *, which is slightly different. The * means "pointer to", so NSInteger * is a pointer to a primitive integer. This is sort of like NSNumber *, a pointer to an NSNumber object, so the compiler allows you to cast it.
Note that casting a pointer doesn't convert the data at the other end of the pointer; it just makes the compiler interpret the same data in a different way. If you actually tried to use the NSInteger * pointer to get data, you would either get garbage data or (for reasons too large to fit within this margin) crash.
In this case, though, once you've Jedi mind-tricked the compiler into thinking that value is a pointer to an NSInteger, you try to pass it to to -addObject:. -addObject: expects a pointer to an object, so the compiler balks at passing a pointer to an NSInteger instead.
** This syntax will work as long as you're using the iOS 6 SDK Xcode 4.4 or later, even if you actually run the app on an older iOS. It will also automatically use the right +numberWithWhatever: method for you, so you don't have to worry about picking the best one. When you're using a numeric literal like 0, the parentheses are optional, but they're required when you use a variable or constant. Of course, you can still do it the wordy way if you want, but there's little point nowadays.