Total newbie question but this is driving me mad!
I'm trying this:
myInt = [myFloat integerValue];
but I get an error saying essentially integerValue doesn't work on floats.
How do I do it?
I'm pretty sure C-style casting syntax works in Objective C, so try that, too:
int myInt = (int) myFloat;
It might silence a compiler warning, at least.
what's wrong with:
int myInt = myFloat;
bear in mind this'll use the default rounding rule, which is towards zero (i.e. -3.9f becomes -3)
int myInt = (int) myFloat;
Worked fine for me.
int myInt = [[NSNumber numberWithFloat:myFloat] intValue];
Well, that is one option. If you like the detour, I could think of some using NSString.
Why easy, when there is a complicated alternative? :)
You can also use C's lroundf(myFloat).
An incredibly useful tip: In Xcode's editor, type your code as say
myInt = roundf(someFloat);
then control/right-click on roundf and Jump to definition (or simply command-click).
You will then clearly see the very long list of the functions available to you. (It's impossible to remember them all, so just use this trick.)
For example, in the example at hand it's likely that lrintf is what you want.
A further tip: to get documentation on those many functions. In your Terminal.app (or any shell - nothing to do with Xcode, just the normal Terminal.app) simply type man lrintf and it will give you full info. Hope it helps someone.
In support of unwind, remember that Objective-C is a superset of C, rather than a completely new language.
Anything you can do in regular old ANSI C can be done in Objective-C.
Here's a more terse approach that was introduced in 2012:
myInt = #(myFloat).intValue;
Related
i'm new to Xcode objective-c and I have a task to make a newsletter that downloadable.
So, I got some source code and tweak a bit but I got some error that said
"Implicit conversion loses integer precision : 'long' to 'int'
here are my code
-(void)downloadIssue:(IssueInfo*)issueInfo{
NewsstandDownloader* downloader = [[AppDelegate instance] newsstandDownloader];
downloader.delegate = self;
long index = [self.publisher indexOfIssue:issueInfo];
[downloader downloadIssue:issueInfo forIndexTag:index]; <-- Error
}
Please help me.
Thank you.
That's just a compiler warning and a mild one at that. If you were dealing with a document that had more than, say, 32000 pages then you might need to be concerned about it.
The way to solve the problem is to either change the declaration of the function you're calling to something like:
[downloader downloadIssue:(IssueInfo *)issueInfo forIndexTag:(long)index]
or, simply use a cast:
int index = (int)[self.publisher indexOfIssue:issueInfo];
"int" isn't usually a good thing to use in Objective C as there are different lengths and capacities to it on different platforms (32 bit versus 64 bit, iOS vs MacOS, etc.). It's better to use something more Objective-C specific, like NSInteger or NSUInteger.
I can write #42, which creates an NSNumber with int value 42. Can I do this with a variable, like #someIntVar? Obviously I tried it and it doesn't work (which sucks because then I have to go through [NSNumber numberWithInt:someIntVar]). Is it possible with a slightly different syntax?
I strongly suggest you read the official clang documentation on the matter: http://clang.llvm.org/docs/ObjectiveCLiterals.html
But, to box a variable, or any expression, you can use parentheses:
id num = #(someIntVar);
I've been developing iOs and OsX applications for several months now and it still feels like I'm doing something wrong. I try to stick to the Guidelines and I try to use the objects Apple provides as often as I can. But it seems they are making my code very hard to understand.
Example:
When I want to just "increment" a NSNumber Object (which is not mutable, but you get what I mean), I use awkward lines like this:
int value = [counter intValue];
counter = [NSNumber numberWithInt:value +1];
Is this really necessary? Are there more elegant ways (i++, inc(i), etc) to do simple things like this? Especially when you're working with coordinates it gets really frustrating and hard to work with.
When working with Objective C I feel like I'm allocating, deallocating and converting objects all the time and wasting so much of my own time and the CPU time with all those conversions. Thanks for your time, I really appreciate your answers and I'm looking forward to your tipps!
Using your example, is there any particular reason you are using NSNumber for a counter? It would be much better to use int so that you can use value++.
The key to good Objective-C code is to use objects when they make sense. Don't be afraid to use non-object data types and don't be afraid to drop down (not the best term) to C when required.
As #sosborn wrote: use objects only when it's required. But: when it's required, and you still feel wrong, simply don't. Write a macro for incrementing an NSNumber, use ARC for let the compiler do the memory management for you as efficiently as possible, etc. If you really worried about time, use C or assembly for time-critical tasks, or C++ if you want OO.
P. s.: NSNumber increment macro:
#define NSNUM_INC(n) do { n = [NSNumber numberWithInt:[n intValue] + 1]; } while (0);
You can write your category for NSNumber to implement the methods you need. For your example the file of category contains the following function:
-(NSNumber *)numberByAddingInt:(int)i
{
...
}
Include this file and then you can call it as:
counter = [counter numberByAddingInt:1];
The discussions I found about setting NSString constants made me code it the following way:
.h file:
extern NSString * const kSectionHeaders;
.m file:
NSString * const kSectionHeaders = #"header";
As the program runs, it has to test words from a text file against a series of NSString constants.
I read memory comparison should work when setting function like stated above:
if (property == kSectionHeaders) {...}
Doesn't work tough :(
The following works, but it was described as a bad solution (slower, what else?):
if ([property isEqualToString:kSectionHeaders]){...}
I feel I've done something wrong. But can't see what!
Please help :-)
Thanks!
J.
== does pointer comparison, it won't compare the values of two objects. isEqualToString: (and in general isEqual:) is the right way to do this - where was it described as a "bad solution"?
Remember variable names are just pointers to objects in memory.
The == operand compares the pointers. It will not be true unless it is comparing the exact same object in memory.
isEqualToString: is your best bet. Don't worry too much about speed. The devices are plenty fast enough to do the comparison in the blink of an eye. The things that really take noticible time are drawing on screen and reading from disk.
Who described that as a bad solution? It is the only proper/correct solution to the problem at hand.
I think this will be pretty simply answered, I'm just stumped on how to get rid of these warnings.
I'm getting 'DebugZoneLayer' may not respond to '-getGID:tileKind' and Initialization makes integer from pointer without a cast when I do this method call:
int blocksCollidableGID = [debugZoneLayer getGID:[NSValue valueWithCGPoint:(NSString*)tileCoord] tileKind:#"blocksCollidable"];
Which I tried all different combinations of casting those types of values.
In DebugZoneLayer.h I have:
-(int) getGID:(CGPoint)tileCoord withTileKind:(NSString*)tileKind;
Thanks
Also the first parameter should not be an NSValue, it should be a CGPoint.
septi is correct about the selector typo, but there seems to be some additional problems as well.
-valueWithCGPoint: takes, well, a CGPoint. The cast to (NSString *) is incorrect. What is tileCoord?
The first parameter is declared to take a CGPoint, not an NSValue, so the boxing doesn't seem necessary in the first place.
Obviously it should be withTileKind instead of tileKind.
Edit: I mean this line ;-)
int blocksCollidableGID = [debugZoneLayer getGID:[NSValue valueWithCGPoint:(NSString*)tileCoord] withTileKind:#"blocksCollidable"];
Edit:
so now you got rid of the warning. Now the compiler finds some other errors, like others already mentioned. Since you seem stuck at this point, I'll try to guess what to do.
You mentioned, that tileCoord is a CGPoint. So there is absolutely no need to cast or convert it anyway. Try this line of code:
int blocksCollidableGID = [debugZoneLayer getGID:tileCoord withTileKind:#"blocksCollidable"];
and see if there are other errors.
There is no casting that's needed for either tileCoord or tileKind
int blocksCollidableGID = [debugZoneLayer getGID:tileCoord withTileKind:#"blocksCollidable"];