Warnings in Objective c with method call - objective-c

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

Related

How do I avoid conversion of signs in a good practice way (without casting)?

I am taking an NSInteger (long int) from a method and using it as a parameter in a method, which takes an NSUInteger (unsigned int).
NSInteger input = [someObject someMethod];
[someOtherObject someOtherMethodWithNSUInteger: input];
This isn't a great idea. What if input is a negative number? How can I do this in a way that is a good practice? Sure, I could just go
[someOtherObject someOtherMethodWithNSUInteger: (NSUInteger)input];
But that's not a good solution because if input is negative, it will not bound it to zero. I could resort to it if there was no other way, but I would rather not.
Solutions that will not work:
Why can't I just make someMethod return an NSUInteger? Or make someOtherMethodWithNSUInteger: take an NSInteger? It's because I don't own them, they are a part of Cocoa Touch.
What about returning nil and using NSError or throwing an exception? The method that I am putting this code in conforms to a protocol, so I can't add an (NSError**) parameter to the method, and returning nil without an NSError explaining why seems like a bad idea because since I don't have access to someMethod's or someOtherMethod's source code, there would be nothing for me to even fix. And if I throw an exception, there is no way for me to catch it because this is code will be used by a closed class who made the protocol.
How can I fix this type conversion problem?
I think the answer somewhat straightforward, and it's basically what you said yourself.
If someOtherMethodWithNSUInteger expects unsigned and the only thing you have is a signed value (returned from someMethod) then two things will happen: (1) half of the possible values expected will never be used, and (2) half of the possible values returned are invalid. No matter what method you use you will always have these issues. So the easiest thing to do is use a simple type-casting, and trim negative values to prevent them being interpreted as very large positive values.
[someOtherObject someOtherMethodWithNSUInteger: (NSUInteger)MAX(input,0)];

Makes pointer from integer without a cast warning in singleton int

Objective-C, xCode for iOS
In a class, I want to assign a singleton integer's value. Right now I have:
[ExGlobal sharedMySingleton].tetraCountEx = tetraCount;
I've got this warning before, and have been able to resolve it, but this seems like I would have to do something different by letting the compiler know that tetraCountEx is an integer. I just don't know how.
That error is a result of trying to store a number as a pointer. With out you posting any code as to how tetraCountEX is declared I can only guess what your problem is.
On reason may be that tetraCountEx is defined as an NSNumber and if that is the case use
[ExGlobal sharedMySingleton].tetraCountEx = [NSNumber numberWithInt:tetraCount];
//or numberWithInteger: or the appropriate type
And the other reason may be accidentally declaring tetraCountEx as a pointer
//Remove the * if this is the case
#property(nonatomic, assign) int *tetraCountEx;

Why do I need to cast before a method of an item of a NSArray can be called?

I am fairly new to Objective-C. Currently porting my own library from C#/Java to objective C.
I now run into a very strange problem for me.
I have a NSArray with several Note objects. I want to transpose on of these notes:
//Note.h
- (Note *) transpose: (int) semitones;
//Main
NSArray *notes = [get it from somewhere];
Note *transposedNote = [[notes objectAtIndex:0]transpose:1]; //Doesn't compile
Note *transposedNote = [(Note*)[notes objectAtIndex:0]transpose:1]//Does compile
Is this happening because there is already a transpose method available in the general libraries?
I thought due to the dynamic nature of objective-C at runtime it would be checked which class objectAtIndex returns and then sends the message to it?
It is my understanding that there is no runtime type checking for the assignment operator in Objective C. Since an array can contain a mixture of types, there is no way for the system to know what objectAtIndex returns.
How about
Note *transposedNote = [notes objectAtIndex:0]; // first line
[transposedNote transpose:1]; // second line
? Notice in the reference that objectAtIndex: returns an id, you will see it is pretty obvious:
In the code above, because id can fit into any object, the first line doesn't need to cast it into Note. In the second line I'm just calling a method on a Note so the compiler is happy.
In your code you are calling methods on the returned id object, so the compiler doesn't understand what you are trying to do. Just assign it to a Note reference and it will be fine.
Yes, the error is because there's already a transpose: method in AppKit. And you're also right that it normally doesn't cause an error when you have two unrelated classes implementing methods with the same name. The reason you get an error is because the two methods either return incompatible types or take incompatible types as arguments. In your particular case, you're seeing both problems:
-[NSResponder transpose:] takes an id and returns void
-[Note transpose:] takes an int and returns an id
These are totally incompatible types, and the compiler does need to know the types involved even if it doesn't know what exact method is going to be called.
It does compile unless you have -Werror set to treat warnings as errors.
It might produce a warning if the compiler doesn't already know about the selector or if the selector is declared in more than one class. In the former case, it should be necessary only to import the interface containing the selector. In the latter case, you'll need to do the cast to suppress the error.

How do I cast id to a float?

I'm having trouble with this code:
NSRect itemFrame;
id item;
// code to assign item goes here.
itemFrame.origin.y -= [item respondsToSelector:#selector(selectedHeight)] ? [item selectedHeight] : [self defaultSelectedHeight];
This is the problematic bit:
[item selectedHeight]
The compiler is assuming that the return type is id. I though that adding a cast would fix this:
(float)[item selectedHeight]
but it doesn't work.
What am I doing wrong? (I suspect the problem is to do with resolving pointers related to id but I can't find any relevant documentation).
you want [[item selectedHeight] floatValue], assuming that the selectedHeight returns an NSNumber.
I know that below code works for iOS 6 SDK. I assume that obj object contains a float value.
id obj;
float fVal;
fVal = [obj floatValue];
You need to look at the declaration of your selectedHeight method. The problem is either that the method is returning a pointer to an object (id), or you haven't imported the header file for item in the file that contains the code snippet, so Xcode assumes it's a pointer by default.
You can't cast a pointer to a float, since they're fundamentally incompatible types. Once you get your declarations straightened out though you should be okay.
The compiler makes that kind of assumptions when multiple classes declare methods with the same name, that return different types. Since your "item" variable is typed as an "id," the compiler doesn't know which of these classes it will be sending the message to at run time, and chooses one.
To avoid this problem, you can inform the compiler what class "item" is an instance of, by declaring it with a specific type instead of the generic "id":
SomeItemClass *item;
You could also avoid it by not declaring identically-named methods that return different types.

How do I convert a float to an int in Objective C?

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;