Pass a variable to decimalNumberHandlerWithRoundingMode? - ios

Forgive me if I use the wrong terminology as I'm still a little new at iOS development. I've built a calculator-type app and I want users to be able to control how numbers are rounded. Here's the code I'm using:
-(NSString*)calculateWidthFromHeightString:(NSString*)height usingDimensions:(Favorite*)dimensions{
int decimalPlaces = [self.userData.rounding intValue];
NSUInteger *roundingMethod;
if ([self.userData.roundingMode isEqualToString:#"up"]) {
roundingMethod = NSRoundUp;
}
else if ([self.userData.roundingMode isEqualToString:#"plain"]) {
roundingMethod = NSRoundPlain;
}
else {
roundingMethod = NSRoundDown;
}
NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:roundingMethod
scale:decimalPlaces
raiseOnExactness:NO
raiseOnOverflow:NO
raiseOnUnderflow:NO
raiseOnDivideByZero:NO];
This works as expected, but I'm getting the following compiler warning where I assign the rounding mode to the pointer "roundingMethod":
Incompatible Integer to pointer conversion assigning to ‘NSUInteger *’
(aka ‘unassigned long *) from ‘NSUInteger’ (aka ‘unassigned long’)
Incompatible Integer to pointer conversion assigning to ‘NSUInteger *’
(aka ‘unassigned int *) from ‘NSUInteger’ (aka ‘unassigned int’)
I don't really know what this means. Any help would be greatly appreciated.

This line:
NSUInteger *roundingMethod;
should be:
NSUInteger roundingMethod;
NSUInteger is a native type, not a class type.

Related

Incompatible pointer types initializing 'dispatch_source_t' (aka 'NSObject<OS_dispatch_source> *') with an expression of type 'NSString *'

Hi I am learner in Objective-c Having a warning of Incompatible pointer types initializing 'dispatch_source_t' (aka 'NSObject<OS_dispatch_source> *') with an expression of type 'NSString *'
- (void)stopAnimating {
pause = YES;
if (timerArray) {
for (NSInteger i = 0; i < [timerArray count]; i++) {
dispatch_source_t _timer = [[timerArray objectAtIndex:i] source];
dispatch_source_cancel(_timer);
_timer = nil;
}
timerArray = nil;
}
[self removeAllFlakesWithAnimation:YES];
}
in dispatch_source_t _timer = [[timerArray objectAtIndex:i] source]; this line, how to solve, timeArray is a NSMutableArray NSMutableArray *timerArray;
We can't tell you what is wrong with your code, there is not enough information for that, but we can tell you what the compiler is doing and why it produces the error it does – then you'll have to resolve it from there.
In your line:
dispatch_source_t _timer = [[timerArray objectAtIndex:i] source];
The LHS declares are variable, _timer, of type dispatch_source_t so the RHS needs to return a value of this type. Let's look at the RHS:
[timerArray objectAtIndex:i]
which BTW you can write more succinctly as:
timerArray[i]
this indexes into an array which you have declared as:
NSMutableArray *timerArray;
the elements of an array like this have type id – which means a reference to any object. The actual type of the objects in the array in this case will not be known until runtime. The next part of the RHS is:
[<a reference so some object> source]
Objective-C allows this and will perform a check at runtime to determine that the reference object does indeed have a method source. However at compile time the compiler can look up the definition of methods called source, it does, and finds that the method returns an NSString *.
So the RHS returns an NSString * and the LHS requires an dispatch_source_t and therefore the compiler reports:
Incompatible pointer types initializing 'dispatch_source_t' (aka 'NSObject<OS_dispatch_source> *') with an expression of type 'NSString *'
Now you have to figure out whether you intended to call source or some other method which does return a value of the right type, etc. HTH
As another BTW to someone learning Objective-C: You are using a for loop to produce an index value for an array, and you only use that value to index the array once. A better way to do this is to use a for/in loop:
for (<YourObjectType> element in timerArray) {
dispatch_source_cancel([element source]);
}
You need to replace <YourObjectType> with the type of object references you've stored in timerArray, and as above the source method needs to return a dispatch_source_t value.
Objective-C has a for ... but there are other really nice ways in which you can iterate through elements of an array. I give one example for array a, in this case of NSString *
[a enumerateObjectsUsingBlock: ^ ( NSString * i, NSUInteger idx, BOOL * stop ) {
// do something with NSString * i
// its index into the array is idx if you need it
// to exit out of the loop do
* stop = YES;
}];

Formatting NSUInteger with %i

I am going through a former employees code and about 20 of these warnings show up:
Values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead
one part of the code where this arises is:
NSUInteger Length;
With:
- (NSString *) description {
// If no value was given, display type
if([Value length] == 0)
{
NSString *type = #"";
switch (Type) {
case DTCompType_Year: type = #"year";
break;
case DTCompType_Month: type = #"month";
break;
case DTCompType_Day: type = #"day";
break;
case DTCompType_Hour: type = #"hour";
break;
case DTCompType_Minute: type = #"minute";
break;
case DTCompType_Second: type = #"second";
break;
case DTCompType_Meridiem: type = #"meridiem";
break;
case DTCompType_MonthName: type = #"month_name";
break;
case DTCompType_DayOfTheWeek: type = #"day_of_the_week";
break;
case DTCompType_Undefined: type = #"undefined";
break;
}
return Length == 0 ? [NSString stringWithFormat:#"[%#]", type] :
[NSString stringWithFormat:#"[%#:%i]", type, Length];
}
No where in apples documentation can I find %i
Apple's Documentation
I have never worked with Objective-C before, and now I have to update this app. I understand that this needs to become an unsigned long, but I don't want to start changing things without knowing why. The app works just fine as is, so are there any inherent consequences for changing these to unsigned long? or even changing the format specifier from %i to %lu?
From what I've read, it could be a matter of the platform. (32-bit vs 64-bit)
This was developed for an iPad 2 in iOS7, and we just upgraded the SDK to iOS8.
I found this post:
NSUInteger should not be used in format strings?
which has given me some guidance, but I need more clarification.
%i is equivalent to %d. Technically, you should have been using %u anyway. The problem is, as you suspect, 32-bit vs 64-bit; NS[U]Integer is [unsigned] int on 32-bit builds, but [unsigned] long on 64-bit ones. Because the iPhone is little-endian, it will "work" as long as the %i/d/u is the last format specified, but it's still wrong. You should cast the argument to be the type the format specifier expects (int/long/unsigned/unsigned long), as the warning message tells you to.
From <objc/NSObjCRuntime.h>:
#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
You can use a boxed literal to allow the compiler and the NSNumber class to handle the details of converting between the various numeric types and their string representations. For example, given the following variable definition...
NSUInteger foo = 42;
...you can create an instance of NSNumber as follows:
NSNumber *myNumber = #(foo);
You can then use the %# format specifier whenever you need to format the value of myNumber. Of course it's easy enough to instead box the original numeric value right in line:
NSString *s = [NSString stringWithFormat:#"The answer is %#", #(foo)];

Zip Archive Progress has Incompatible block pointer types assigned

I'm merely trying to run an app in simulator to see if assets and changes to a .json file were implemented correctly, however, when I attempt to run the app it fails and returns:
Incompatible block pointer types assigning to 'ZipArchiveProgressUpdateBlock' (aka 'void (^)(int, int, unsigned long)') from 'void (^)(int, int, int)'
The whole block is below and the issue references the specific line:
zip.progressBlock = ^ (int percentage, int filesProcessed, int numFiles)
ZipArchive* zip = [[ZipArchive alloc] init];
[zip UnzipOpenFile:pathToZipFile];
zip.delegate = self;
zip.progressBlock = ^ (int percentage, int filesProcessed, int numFiles){
[self showProgress:PackageDownloadStateUnzipping progress:(float)percentage/100.0f];
};
BOOL success = [zip UnzipFileTo:unzippedDestination overWrite:YES];
if ( !success ){
self.state = PackageDownloadStateUnzipError;
}else{
self.state = PackageDownloadStateUnzipped;
}
Read the error. It tells you the problem. The block expects three parameters with type of int, int, and unsigned long. But your block has three int parameters.
Simply change the 3rd parameter's type from int to unsigned long.
zip.progressBlock = ^ (int percentage, int filesProcessed, unsigned long numFiles){
[self showProgress:PackageDownloadStateUnzipping progress:(float)percentage/100.0f];
};
Well, the block you assign takes (int,int,int) but the ZipArchive expects you to pass one that takes (int,int,unsigned long) -- at least, that's what the error message says.
I'm surprised that its getting to running - are you sure it isn't failing at compile time?

Incompatible pointer to integer conversion sending 'id' to parameter of type 'int'

I guess it's really simple but I can't find the way to work this out...
I have a method like this
- (int)showQuestionMethod:(int)number;
I'm creating NSMutableOrderedSet in loop like this which works fine.
while (count < numberOfQuestionsInTest) {
randomQuestionNumber = 0 + arc4random() % (numberOfQuestions - 0);
[_randomQuestionNumberArray addObject:[NSDecimalNumber numberWithInt:randomQuestionNumber]];
count = [_randomQuestionNumberArray count];
}
Then when I want to call a method with this line and I get an error (Incompatible pointer to integer conversion sending 'id' to parameter of type 'int')
int showQuestion = 0;
[self showQuestionMethod:_randomQuestionNumberArray[showQuestion]];
Can anyone offer solution? Thank you!
Your _randomQuestionNumberArray contains NSDecimalNumber instances. But your method takes and int parameter. You need to properly convert them:
[self showQuestionMethod:[_randomQuestionNumberArray[showQuestion] intValue]];

Incompatible inter to pointer conversion

The following code generates compiler warning (below the code)
NSUInteger positionat = [_bhkButtons indexOfObject:sender];
BOOL val = (BOOL) [_searchModel.BHkNo objectAtIndex:positionat];
val = !val;
[_searchModel.BHkNo insertObject:val atIndex:positionat];
Incompatible integer to pointer conversion 'BOOL' (aka 'signed char') to parameter of type 'id'
I'm a newbie to Objective - C. Please help.
Since BOOL is a primitive data type and arrays take in objects, you have to box/wrap the BOOL variable. You can use the NSNumber class for the same as shown below.
[_searchModel.BHkNo insertObject:[NSNumber numberWithBool:val] atIndex:positionat];

Resources