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.
Related
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.
Why is it that you can do something like this?
NSInteger something = #"something";
It feels weird that this doesn't throw an error and instead returns some number that, in fact, is an NSInteger.
For me it says Incompatible pointer to integer conversion initializing 'NSInteger' (aka 'int') with an expression of type 'NSString *'
I feel, what you get number is memory address of that NSString.
In Languages Like Objective C, When You Define a class or a constant string(What you define like #"something" is a constant string), it will be stored somewhere and the pointer to it will be used. Pointers are 32-bit and 64-bit. 32-bit pointers are 32-bit Integers so they can easily be casted to an integer. So there is no way to throw an error as it is a legal assignment.
it's the same line of code
NSInteger something = [#"something" integerValue];
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.
What's the largest value an NSNumber can store?
// ok
NSNumber *value = #(1 << 31);
// gives compiler error, so max NSNumber is 32-bit uint?
NSNumber *value = #(1 << 32);
NSNumber is actually a class cluster, meaning that when you create an instance you may be getting any of a variety of concrete subclasses, each capable of storing a different kind of numeric type. The actual types available, and their sizes, may be machine-dependent.
Looking at the NSNumber documentation shows you the different kinds of numbers you can store: the two largest integer options would be +numberWithLongLong: (or +numberWithUnsignedLongLong:), which stores a long long, and +numberWithInteger: (or +numberWithUnsignedInteger:), which stores an NSInteger. The maximum NSNumber values are therefore limited by these types.
The Foundation documentation states:
When building 32-bit applications, NSInteger is a 32-bit integer. A 64-bit application treats NSInteger as a 64-bit integer.
The compiler is smart and will create an NSNumber of the same type as your numeric literal. As mentioned in the comments above, you can use #(1ULL << 32) if your machine has an unsigned long long type with more than 32 bits.
Furthermore, NSNumber is toll-free bridged to CFNumber, meaning you can try out functions like CFNumberGetByteSize() for yourself — and have a look at the Number Types section of the CFNumber documentation. You'll see these are basically the same as the NSNumber options.
Additionally, the NSDecimalNumber class, a subclass of NSNumber, provides the +maximumDecimalNumber method which you can use to find the maximum value that can be stored in an NSDecimalNumber. NSDecimalNumber, and the floating-point types, may be able to store bigger numbers than the integer types, though with decreasing precision.
What is the benefit of using NSNumber from Foundation Framework instead of basic C types (int, float, double)?
Using NSNumber:
NSNumber *intNumber;
NSInteger myInt;
intNumber = [NSNumber numberWithInteger: 100];
myInt = [intNumber integerValue];
Using pure C:
int intNumber;
intNumber = 100;
Seems a lot easier and economic to use C.
I know NSNumber is an object (or class?) type, but why would I use them instead simple C variables? When should I use them?
The purpose of NSNumber is simply to box primitive types in objects (pointer types), so you can use them in situations that require pointer-type values to work.
One common example: you have to use NSNumber if you want to persist numeric values in Core Data entities.
You can and should use primitives for calculations (unless with decimals, in which case you use NSDecimal or NSDecimalNumber).
If you need to pass a number as an object, use NSNumber.
If you need to make arithmetic operations, you can use int and double. If you don't want to bother with 32/64 bit issues, you can use NSInteger and CGFloat.
Because with dealing with passing of parameters with certain objects, using a basic data type will not work. Also, the NSNumber class gives you options for converting values into other datatypes quickly.