Reputation: 36003
I have a class and this class has a delegate protocol. I create an object in the main class using this class and assigned the main class as the delegate. The main class has a property I would like to read inside the created class. Then I do this:
BOOL prop = [self.delegate myProperty];
Xcode complains that "delegate
may not respond to myProperty
"
If I am sending a message to self.delegate
to read myProperty
, and generally Xcode never complains when you send a message to an not casted object, why do I have to do that
BOOL prop = [(myMainClass *)self.delegate myProperty];
to make it work?
To be more clear, here is an example of a message sent to an object without having to cast:
[self.myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop){
int Number = [[obj dictionaryOfNames] count];
}];
self.myArray
is an array of objects from another class that are dictionaries and have this property dictionaryOfNames
. Xcode never asked me to cast this:
int Number = [[(myOtherClass *)obj dictionaryOfNames] count];
as I had to above for myProperty
.
Upvotes: 2
Views: 1528
Reputation: 923
You haven't shown enough code to give a completely definitive answer, but in general terms I would expect that the definition of your delegate is not just id, you've probably used NSObject* or something similar.
The compiler is doing "static" analysis of your source code and trying to determine whether or not the object specified by "self.delegate" might implement that method. If the data type is, say, NSObject*, then the compiler looks through that specific class definition to see if your method is present; if it isn't, then you'll get a warning.
If the data type of the message receiver is id, the compiler tends to give up and say "well, it could be anything so I'll assume this will work".
The result of the expression [obj dictionaryOfNames] is probably of type NSDictionary and the compiler can see that that particular class does respond to the count method.
Note, you can also get this problem if you have specified a class name for a property, but the compiler cannot see the entire class definition from this file. For example, if you have
myobject.h:
@class Something;
@interface MyObject
@property (retain) Something *delegate;
@end
myobject.m:
#import "myobject.h"
[self.delegate doItYouFool];
then the compiler can see that the result of the expression 'self.delegate' is of type Something* but it can not see the actual definition of that class and thus can't look through its supported messages. This usually results in a warning about 'forward definitions'. To fix it, you should import "something.h" into the .m file, so that the compiler has full knowledge about the classes it is working with. To just silence the warning, you cast to id
[(id)self.delegate doItYouFool];
You may, of course, also be getting warnings that 'doItYouFool' isn't a known method, again because you haven't included the header file that defines that message.
Upvotes: 0
Reputation: 7344
Different classes can conform to a protocol. If you declare that you conform to a protocol you just say that you will implement the requiered methods but you can implement it in a UIView
, UIViewController
, MyOwnClass
, MyOtherClass
etc.
Thats why a property is normally declared like this
@property (nonatomic, weak) id <MyProtocol> delegate;
So you just say your delegate is an object which conform to the protocol.
Upvotes: 5