Does a method which I check for with respondsToSelector have to actually exist?
What if I only define it in the interface part and fail to implement it? I'm looking at a poor-man's virtual function in Objective-C.
First, yes the method actually has to exist for the check to succeed in the context you describe. respondsToSelector: will return NO if the method is not implemented.
More importantly, I think you mean a poor man's pure virtual function in Objective-C. All instance methods are "virtual" in Objective-C; since method lookup is done a run-time, the subclass' implementation will always be used, even from a pointer of the superclass type. In Objective-C, there is no such thing as a pure virtual base class. You can often achieve what you want by either using a #protocol to define an API or using a base class that provides an implementation that throws an NSNotImplementedException as its body. Subclasses would obviously have to override the implementation, making it effectively pure virtual.
Given that calling respondsToSelector: only makes sense when you don’t know whether a method exists, it’s not entirely clear what you mean.
If you mean, does some implementation of a method with the specified selector have to exist somewhere, the answer is no. Selectors merely represent names of methods. The #selector directive doesn’t reference any aspect of any method implementation.
respondsToSelector will return NO, since the selector isn't callable at run-time. The interface part only affects compilation.
Related
I find a c++ system method causes crash in ios and I try to swizzle the method. However, I do not how to do that because it's a method of a c++ class. Anyone know whether can I do that?
Method swizzling is unique to objective-c (and even there one has to use it carefully), and is not applicable to c++.
I suppose that you don't have access to the source code of the c++ class.
Then the only way to "exchange" the implementation of a method at a specific c++-class is to derive a subclass, override the method, and then make sure that the subclass is used instead of the other class. It is still unlikely that you have a chance; the method being not virtual, the class to be replaced being used in non-polymorphic ways, the class to be replaced already having several subclasses, each of these points will prevent you from being successful.
Good luck though!
Is there a way to indicate to the compiler that a class object conforms to a protocol?
As I understand, by creating +(void)foo class methods, an instance of that class object will have those methods as instance methods. So, as long as I create +(void)foo methods for all required protocol methods, I can have a class object act as a delegate.
My problem of course is that in the class's header file, I only know how to indicate that instances of the class conform to the protocol (as is typically the case). So, the best I've figured out is to cast the class object like so:
something.delegate = (id<SomethingDelegate>)[self class]
Any ideas?
Related, but different:
ObjC: is there such a thing as a "class protocol"?
What you're doing now is correct as it will silence warnings which is your goal. You will be sending the class object messages defined in the protocol for instances which is a bit confusing, but the runtime doesn't care.
Think about it this way: you want to set a delegate to an object that responds to the messages defined in the protocol. Your class does this, and your class is also an object. Therefore, you should treat your class like an object that conforms to that protocol. Therefore, what you've written is completely correct (based on what you're trying to do).
One thing to note, though, is this class will not properly respond to conformsToProtocol:. This is generally okay for a delegate setup anyway (delegates don't usually check if the class conforms — they just check if it can respond to a selector).
As a side note, one thing you can do syntactically is:
Class<SomethingDelegate> variable = (Class<SomethingDelegate>)[self class];
The difference here is that the compiler will use the class methods from the protocol instead of instance messages. This is not what you want in your case, though.
There is no Objective-C syntax to indicate that a metaclass conforms to a protocol.
I think you can do it at runtime, by using class_addProtocol on the metaclass. But I haven't tried it.
I guess you could also write a +conformsToProtocol: method on your class, and lie about your conformance. This could have unexpected side-effects, since there's already a +conformsToProtocol: on NSObject (in addition to -conformsToProtocol:).
Neither of these will eliminate the need for a cast to shut the compiler up. Just use a singleton.
I have a class with several subclasses.
They all override a class method, but I don't have a specific implementation for the method in the superclass.
Since I can't just declare it in the interface but I need to implement it as well (to avoid debugger warnings), I was wondering if I can just provide empty implementations of the method in the superclass.
The reason why I'm adding the methods definitions to the superclass is that I've a multi-target project, the current application delegate is considered with the specific overridden method:
[(GenericDelegate *)[NSApp delegate] myMethod];
thanks
Yes, this is a perfect normal practice. In fact, it has a name: a "Template Method." You search for that in the Cocoa documentation.
You will find that Apple also does it occasionally in their own code. The drawRect: method in UIView is the first one that comes to mind.
So, anyway, yes, if it suits your needs, I would go ahead and do it. Just make sure that you think through whether or not, for example, a protocol wouldn't suit your needs better.
There are other options as well. Check out the answer/discussion over here: Does Objective-C have something like C++ virtual functions?
All methods are virtual in objective c, "pure" virtual (as in C++) function don't exist and hence the equivalent methods in objective c need an empty implementation in the superclass, just to silence the compiler warning (I don't think there is any other way to do so). There is nothing wrong with that. This post is related to your question.
I want to go to there. Seriously though, how does one implement a pure virtual method in an "Apple" way? Do you use a Protocol with your base class and throw exceptions on those methods?
When you program in Objective-C you need to purge your mind of such things as virtual methods. You don't call methods on Objective-C objects, you send messages to them. Objects either respond to messages or they don't, but due to the dynamic binding, you can't tell this until run time.
Thus, you can declare a method on a base object and not not provide an implementation, no problem (except for the compiler warning), but you can't have the compiler flag up when you directly instantiate an object with such methods and it won't throw an error at runtime unless you actually send that message to the object.
The best way to create "virtual" base classes (in my opinion) is to declare the method and give it a stub implementation that throws a suitable exception.
In Objective-C, there is no pure virtual support as in C++.
A simulation would be that you declare a method in your interface but don't implement it in your .m file. Of course you'd get compiler warnings but IIRC you can turn those off. But you won't get warnings/errors if you don't overwrite them in the subclass, which you get in C++ (IIRC).
An alternative would be to implement them with just an NSAssert(NO, #"Subclasses need to overwrite this method"); body. Still, you'd only catch this at runtime, not compiletime.
Depending on what you're doing the delegate pattern may be more appropriate than a subclass, where the delegate is defined as id<YourDelegateProtocol>. The compiler will generate a warning if the required methods in the delegate protocol are not implemented.
Subclassing is generally avoided in Objective-C since objects cannot inherit from multiple superclasses but they can implement multiple protocols.
You should use the:
- (void)doesNotRecognizeSelector:(SEL)aSelector method.
As noted by Apple, here: https://developer.apple.com/library/mac/#documentation/cocoa/reference/Foundation/Classes/NSObject_Class/Reference/Reference.html
You have a few options, but you're on the right track.
ObjC doesn't support this directly, forcing subclasses to implement a protocol is the best way to check it at compilation.
'Secretly' implementing the method in the base class and asserting is what I do to confirm the subclasser has subclassed correctly at runtime. Some people have mixed feelings about assertions, or must leave them active, so that's not always a good solution.
You can also force subclasses use a specific class constructor and initialization sequence, then verify they have implemented everything required before returning an instance, in case compiler warnings don't cut it.
But ObjC is missing some lang features which allow clients to shoot themselves in the foot, or workaround what they wish so... you shouldn't get too stuck on enforcing it.
note: Exceptions are very uncommon (and a bit unsafe, too) in ObjC.
A virtual method is a method whose behavior can be overridden within an inheriting class by a function with the same signature (i.e same name with same number of params and type of params).
Example:-
#implementation BaseClass
-(void)viewDidLoad
{
[self virtualMethod:123];
}
-(void)virtualMethod:(int)param
{
//implement this method in subclass
}
#end
////////////////////////////////////////////////////
#interface ChildClass:BaseClass
#end
#implementation ChildClass
-(void)virtualMethod:(int)param
{
NSLog(#"There is no keyword "Virtual" in Objective C.");
}
#end
Output:-
"There is no keyword "Virtual" in Objective C."
If subclass in objective-c wants to override a super class's method, does it have to match the return type too?
Yes, it must have the same selector.
update:
IIRC the arguments also needs to have the same types.
update:
It seems that all methods of the same selector needs to have equivalent types across all classes when linking dynamically, not so with static linking: linky
Yes, It be same,
But one thing to be noted is you need to pass the super-class of return types.
Eg:
-(UIScrollview)method:(id)argument;
you can return UIview as well. (simply saying super class of return types).