Cocos3D - 'May not respond' warning on dot notation - ios7

I am using Cocos3D and this function give me a 'may not respond' warning:
[CClayer.CC3scene someFunctionFromCC3scene];
I know one way to resolve this is to have a Function in CCLayer to make CC3scene call someFunctionFromCC3scene. But is there any other way to do this? Thanks!

More likely you're not importing the corresponding header. For example #import "CC3Scene.h". I suppose this can happen if the return type of the CC3scene property is id instead of the actual class.
Or the compiler is correct about this and it will crash with "does not respond to selector" when you run it. In that case CC3Scene does not implement the someFunctionFromCC3scene selector. Check spelling and parameters, and of course that the class actually implements that selector and has it declared in the #interface.

From the look of your example, there are several things that might be going wrong:
You might be confusing CCLayer with CC3Layer. CC3Layer is a subclass of CCLayer that supports displaying a 3D scene. Be sure you are instantiating a CC3Layer.
If you really are using a CC3Layer and the CC3Scene property (which is actually cc3Scene) is returning an instance of CC3Scene, then, as LearnCocos2D indicates, verify that the method you are invoking actually exists in the CC3Scene class. If you provide the specific method name here, then I can provide further help.
If the someFunctionFromCC3Scene is actually defined and implemented in your custom subclass, then you should cast the CC3Scene instance to your custom subclass before invoking that method:
[((MyCC3Scene*)aCC3Layer.cc3Scene) someFunctionFromMyCC3Scene];
...Bill

Related

'does not have member' when calling objective C setter method from Swift

After importing the objective C robbiehanson/XMPPFramework into a swift project (setting up build setting, bridging header, etc). I am able to call normal methods in the imported classes and set properties directly.
However, certain instance methods that set properties cause immediate errors as if they don't exist in the instances I'm calling them on. For example:
- (void)setMyJID:(XMPPJID *)newMyJID
{
[self setMyJID_setByClient:newMyJID];
}
Or even the setMyJID_setByClient:newMyJID method which actually does the setting.
In two separate objective c example projects I have looked at, the setMyJID method is being called from other classes. However, while I am able to call other instance methods on the class, I can't call this one. Since I am not very familiar with objective c, I though this might be because it wasn't declared in the header file, causing some swift specific problem, but attempts to add a declaration for it did not help.
I am able to set the relevant property directly, but this is not only undesirable, I also would like to understand why I am not able to call certain methods.
I am attempting to make the call on an instance of the XMPPStream class like this
//This shows immediate error: XMPPStream does not have a member named 'setMyJID'
stream.setMyJID(XMPPJID.jidWithString(someXMPPAddress)
// This works perfectly
stream.myJID = (XMPPJID.jidWithString(someXMPPAddress))
Any help would be appreciated.
In the XMPPStream class, myJID is declared as follows:
#property (readwrite, copy) XMPPJID *myJID;
In Objective-C, this means that there are actually two methods on the XMPPStream class that conform to the following signatures:
- (XMPPJID *)myJID;
- (void)setMyJID:(XMPPJID *)myJID;
So, from Objective-C code, you can call them like any other method. However, as you know, you also have the option of using the syntactic sugar in the language known as "dot notation":
// getter with dot notation
XMPPJID *jid = stream.myJID;
// setter with dot notation
stream.myJID = jid;
However, in Objective-C, these dot notation expressions are directly translated into calls to the getter and setter. They're just there to look nice.
Things are different in Swift. When you have a property, like this one:
var myJID: XMPPJID
this does not mean that there exist separate getter and setter methods, like you might be imagining:
func myJID() -> XMPPJID {}
func setMyJID(jid: XMPPJID) {}
In Swift, you must access properties using dot syntax.
Knowing this, your problem becomes obvious. When you tried:
stream.setMyJID(XMPPJID.jidWithString(someXMPPAddress)
Swift tried to run the instance method setMyJID of stream, and found, rightly, that it did not exist! This, of course:
stream.myJID = (XMPPJID.jidWithString(someXMPPAddress))
works perfectly, because you're setting a property as Swift requires.
As an educational aside, you may sometimes see cases where, when accessing Objective-C properties from Swift, you not only can, but must use the getter and setter methods - dot notation won't even work! This seems totally counterintuitive, but there's a good reason for why this happens. One example of this that I can think of off the top of my head is the verbosely-named UIView property translatesAutoresizingMaskIntoConstraints, used for view layout. If you try to use it in Swift, like so:
// Set translatesAutoresizingMaskIntoConstraints to false on self
translatesAutoresizingMaskIntoConstraints = false
you would get a compilation error! Specifically,
Cannot assign to 'translatesAutoresizingMaskIntoConstraints' in 'self'
Why? The answer lies in the UIView headers:
- (BOOL)translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES
- (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag NS_AVAILABLE_IOS(6_0);
It turns out that this "property," like many others in the Cocoa frameworks, is actually just a pair of methods that look like property accessors. Because of how Objective-C translates dot notation into method calls, you'd never notice before. Now, though, Swift is stricter – to get and set this "property," you must call the appropriate methods.

Property with 'iboutlet' attribute must be an object type (invalid 'BOOL' (aka 'signed char'))

After updating my project to 10.7 SDK and switching debugger,
I got this message:
Property with 'iboutlet' attribute must be an object type (invalid 'BOOL' (aka 'signed char'))
It was perfectly working before the update.
Any hint on how to fix that?
you have to import the map framework (MapKit/MapKit.h)
#import <MapKit/MapKit.h>
If you are using custom classes for components (i.e. subclassing from UI*) remember that you need to import the .h file for your class so your property pointer is not just an (id) for the compiler.
Try to unlink and link again the IBOutlet, or try to assign the boolValue to that variable holding the object.
As far as i know, with the new SDK many things are becoming deprecates and things won't work properly. That's why i hate using beta's!
IBOutlets are always objects, they are values that are referenced in xibs/nibs, you can't really do that with scalar values. If you need to set a boolean then you can call a setter in an object's -awakeFromNib method, or depending on what you are doing: kvo or delegation may be appropriate.

Objective C shenanigans

In my quest to be the grandmaster of Objective C, I keep running into it's subtleties, which I want to share with ya'll and gain an understanding why
1) I have two init methods, the one that is inherited by NSObject for my Objective C class and one is a custom method that I create off my own, let's say
initCustomMethod:(int)par1 argument2:(int)par2;
My Aim is to call initCustomMethod through the provided init method, essentially
-(id)init{
return [self initCustomMethod:1 argument2:3];
}
Naturally, maintaining the order, I have init appearing before initCustomMethod in the .m file. Xcode warns me telling me that the initCustomMethod is not found, I go ahead and shuffle the order and have init appearing after initCustomMethod is declared and there is no such warning message anymore and everything is fine.
I concur that the order is important since it's essentially derived from C, however I am not sure of this. Because, i shuffled the order of some properties and their custom methods, with the properties #synthesize being declared after the custom setter method for a given property, but there was no such error replica.
Can anyone point out the malice here?
Thanks guys!!!
Very cool guys, thanks for helping me out with this. Also, since I have a custom init method, I am initializing the super in this method and using the original init method to call the custom init method.
Anything wrong with this?
Before you reference it anywhere, you should declare initCustomMethod:argument2 in your interface, which would usually be in your header file.
For example, you would usually have a .h file that looks like:
#interface MyClass
{
//instance variables
int anInstanceVariable;
}
// properties
#property (nonatomic, assign) int aProperty;
// methods
-(id)initCustomMethod:(int)par1 argument2:(int)par2;
#end
And if you did this, the order in which you define init and initCustomMethod:argument2: won't matter. This is because the declaration tells the compiler that you are going to define the method, and what it will look like, so it isn't confused when you use it later.
It's a bad idea in Objective-C to use a function or a method before it is either declared or defined. Putting initCustomMethod:argument2: before init means that the former is already defined in the latter. But if you'd just declare it in the header, it wouldn't matter which order they went in.
Add your custom method name in your header file - the compiler just goes through things in order. If you don't have a forward declaration, the compiler won't know what to do with that call. You're going to need to put it in the header if you want other parts of your program to be able to call it anyway.

If object respondsTo still throws warning

I am working on a project where I have a class which has UIView property. I also define a class which is a subclass of UIView which defines a certain method. If I have the following code, I get a warning when I build:
// In this example, myView is UIView property which *may* contain a UIView or
// my subclassed-UIView which has the myMethod method
if([myView respondsToSelector:#selector(myMethod)]){
[myView myMethod]
}
The warning is "UIView may not respond to '-myMethod'". The warning obviously doesn't stop the app from being built, but I am just trying to figure out how to deal with it. Is this the correct way to do this? Is there a way to stop this warning?
The warning is only because the compiler doesn't know if that view is your custom subclass. Of course, at runtime it will work fine, since it will be a subclass. You have two options to fix it:
[myView performSelector:#selector(myMethod)];
(So the compiler doesn't check the method call at all)
Or, better:
[(MyViewClass *)myView myMethod];
That way the compiler acts as if the object really is your view subclass (after you performing the check of course).
For that matter, it might make sense to check for your class rather than the method:
if ([myView isKindOfClass:[MyViewClass class]]) { ...
You can use:
[myView performSelector:#selector(myMethod)];
This is a static typing warning, telling you that the type the variable is declared as does not respond to that selector. Since you're actually using a subclass that you've confirmed responds to the selector, you know this isn't a problem, but the compiler isn't smart enough to figure this out. There are a few ways you can fix this. In decreasing order of safety:
Cast the variable to what it actually is that does respond to the selector, either a specific class or a protocol. You'll still need to import the appropriate header or the compiler will suspect you mistyped something. Which option is best depends on your situation (e.g. whether there's one "correct" class to cast to).
[(id<SomeProtocolWiththatSelector>)myView myMethod];
[(SomeUIViewSubclass *)myView myMethod];
Cast the variable to id to disable static typechecking. You'll still need to import a header with the declaration so the compiler knows some method exists or it will still give the "I'm not sure if this is a real method" warning.
[(id)myView myMethod];
Use performSelector:. This will not do any checks at compile-time, so you don't need to import any headers besides Foundation, but the compiler won't catch any typos either, so any mistakes you make mean the program goes boom at runtime.
[myView performSelector:#selector(myMethod)];

Passing a value from one object into another with Objective-C

I have a class called GameScene, with is a subclass of a cocos2d Scene.
In there I have two layers. GameLayer and ControlsLayer. You can probably tell already that I want the ControlsLayer to move stuff around in the GameLayer. To be precise, I'm trying to control a cPBody in the GameLayer from the ControlsLayer.
At the moment, I'm trying to route the instructions from the ControlsLayer, back up into the GameScene and then back down into the GameLayer. If that makes sense. Anyway, I can't get it to work. I have a PHP background so I think I'm incorrectly applying my PHP experience to Obj-C.
My thinking is, I should be able to access a property inside a class/object using something like
aThing *someThing = someInstance->aThing;
From the sample code I've been looking at, it looks like this should work. But it doesn't. Here's the code, stripped down to as much as possible http://pastebin.com/d49c9d0be
Rather than knowing how to fix this particular issue, The question is, what don't I understand?
In Objective-C you need to define accessor methods to get at the instance variable, you can't directly access it like that unless you're calling it from the same class type (for instance when you're implementing the NSCopying protocol and need to set private variables, but don't worry about that now).
The easiest way to do that is to define a property in your header using #property(retain) SomeClass *name;, and have Objective-C generate it by putting #synthesize name = instanceVariable; in your implementation. You can then access the variable outside of that class using object.name; or [object name];. For more information take a look in the documentation for properties and Object Oriented programming.
You're not exposing the gameLayer.myBody property in any shape. You'd have to use the #property declaration (assuming objective-c 2.0) (here's an example).
I don't have any PHP background, so I don't know how it may be different in PHP.
The correct way to access a property in an object is as follows:
aThing * someThing = someInstance.aThing; // new style
or
aThing * someThing = [someInstance aThing]; // old style
If you were coding in c, the -> operator would make sense. In objective-c, however, objects are always passed around through pointers. No objective-c variable ever actually holds an object, they just hold pointers to objects. The language designers simply decided to use the [] or . syntax to access members, so that's what we have to do!