Objective-C "Override" Specifier - objective-c

In Java, C++11 and some other languages you can specify that a method is intended to override another method from a base class or interface, if you then at a later point remove the method from the base class you get a compiler error. I use protocols with optional methods a lot and find that if I remove a method from there I have a tendency to forget to remove the code that implemented the method. This does not generate an error or a warning, thus creating a "dead" method.
Consider:
#protocol Prot <NSObject>
#optional
- (void)bar;
- (void)tempBar;
#end
#interface MyType : NSObject <Prot>
#end
#implementation MyType
- (void)bar { /**/ }
- (void)tempBar { /**/ }
#end
If I at one point remove tempBar from the protocol, I would like to get at least a warning from tempBar being implemented in MyType.
Is there any way in Objective-C to specify that a method is expected to be an implementation of a protocol method?

Objective-C is a dynamic language and this is rather impossible to enforce at compile time. Note that in Obj-C you can actually call methods there are not even there and the app won't crash (well, the default implementation will raise an exception but you can change that behavior).
The method can be also added in an extension, or added at runtime. Or it is just not present in the header.
Note there is also the opposite problem. When subclassing, you can override a method which you don't even know is there, because it is not present in the headers.
This is one of the reasons why Apple is moving to a more predictable language, that is, Swift.

Related

Passing a Class which conforms to a protocol as an argument

Is there a way in Obj-C to pass a class as a parameter which conforms to a protocol?
For example, say I have a slew of classes which conform to this protocol:
#protocol IMyProtocol <NSObject>
+ (id)someMethodINeed;
#end
I want to set up a method which takes in any class which conforms to this protocol.
#interface SomeClass : NSObject <IMyProtocol>
#interface AnotherClass : NSObject<IMyProtocol>
I want to make a method like this:
- (void)doSomething:(Class<IMyProtocol>)customClass
{
[customClass someMethodINeed];
//A whole bunch of other code I don't want to copy/paste each time
}
And call it with any of those classes
[self doSomething:SomeClass];
[self doSomething:AnotherClass];
I can't figure out the syntax though. Is this possible?
To make your code work you just need to pass the class, change your two calls to:
[self doSomething:SomeClass.class];
[self doSomething:AnotherClass.class];
However while this works the compiler is not doing the checks you probably expect. You can pass any class to doSomething: regardless of whether it implements your protocol; and [customClass someMethodINeed] is a dynamic call resolved (or not) at runtime and may produce an "unrecognized selector sent to class" error.
(Objective-C always does dynamic method lookup but with typed values the compiler is usually able to determine at compile time whether the runtime resolution will succeed or not. What you are are seeing here is the behavour you get when you program using id.)

Can we not declare methods in the header files?

I am watching the Stanford University iPad and iPhone application Developments course video. The instructor says in the video we can control-drag an UI object to the implementation files to create an action. But in this way the method will not declare in the header file. Does this mean it is ok to implement methods in the .m file but not declare in the .h file?
Depends on how you define "ok" :-)
Objective-C uses dynamic method lookup and does not really enforce access ("private", "public", etc.) specifiers. So you don't need to declare any method in a header file.
However you will end up fighting the compiler as it does do a fair amount of type-checking unless you persuade it not to, and you'll lose by doing so.
You are not required to declare in the header file all methods in the implementation. But if not in the header file obviously you cannot reference them by literal name in another file, nor can you "forward reference" them in the implementation file.
(Note that this is not that different from regular C, but is different from methods of a class in C++.)
It's "OK" to not declare methods in the header yes, under certain circumstances. For instance, if using ARC then the compiler generally needs to know the method signature so it can do the right thing. But basically all it means is that wherever you're using the method, it must already know about the method you're calling.
Since you're talking about Interface Builder, that's slightly different in that it will know about all methods since it can "see" the whole context of your header and implementation files and know that a method exists. i.e. in my terminology above, the method has been defined before it's used.
With regard to defining before use, the general accepted approach is to either:
Define a method in the interface file (.h). e.g.:
MyClass.h
#interface MyClass : NSObject
- (void)someMethod;
#end
MyClass.m
#implementation MyClass
- (void)someMethod {
// do something
}
#end
Define a method in a class continuation category. e.g.:
MyClass.h
#interface MyClass : NSObject
#end
MyClass.m
#interface MyClass ()
- (void)someMethod;
#end
#implementation MyClass
- (void)someMethod {
// do something
}
#end

Objective-C dynamically created methods and compiler warnings

If I generate methods dynamically on runtime and then call them - how can I convince compiler that the class will respond to undeclared (generated) methods and make it not throw warnings?
Update in regard to answers
When I generate the methods - their name is not known at compile time. To give an example - if I have a view controller MyFooController and it's initiated with method initWithFoo:(Foo*)foo, I'd be able to generate method like pushMyFooControllerWithFoo:(Foo *)foo for UINavigationController. Hence you notice that declaring such methods would be counter-productive.
This doesn't directly answer your question, but if I was generating method names (presumably from strings), I would call them using the string names, hence bypassing the compiler warnings.
[fooController performSelector:NSSelectorFromString(#"pushMyFooControllerWithFoo:") withObject:foo];
That way you are responsible for the validity of the generated method names.
Since you are adding methods on runtime, so you should also invoke them with runtime function, objc_msgSend or performSelector:withObject:for example, so the compiler will not going to warn you anything.
Well, if you call them, you know their signature, and if you know their signature, you can declare them, can't you?
Declare this method in a category for NSObject and make an empty implementation:
#interface NSObject (DynamicMethodsCategory)
- (void)doSomething;
#end
#implementation NSObject (DynamicMethodsCategory)
- (void)doSomething
{
}
#end
In your object you can call it without any warnings:
#implementation MyObject
- (void)someMethod
{
[self doSomething];
}
#end
Then generate implementation of [MyObject doSomething] dynamically, it will be called instead of NSObject's one.
Update:
Alternatively, the method can be declared in a category for the object. This suppresses the compiler's Incomplete implementation warning. However, I think this is not a good workaround, because the application will crash if the method is not created dynamically in runtime before it is called.

Objective-C: How to view a protocol?

For every object that can have a delegate, there is a corresponding protocol, that declares the messages that the object can send it's delegates. The delegate implements methods from the protocol for events it is interested in.
How can one view the protocol in order to find out what functionality needs to be implemented?
Protocols in Objective-C are non-essential, but they are useful; Protocols are usually declared in header (.h) files:
#protocol MyAwesomeProtocol
-(void)thisMethodIsRequired;
#optional
-(void)theseMethodsAreOptional;
#end
... and are usually used in a couple of places:
1: In an instance variable declaration:
#class Foo : Bar
{
id<MyAwesomeProtocol> someIvar;
}
#end
2: In property declarations:
#class Foo : Bar
{ }
#property (assign) id<MyAwesomeProtocol> someProperty;
#end
3: In code (Try to avoid this, but it's legal):
if(...)
{
[(id<MyAwesomeProtocol>)obj foo];
}
If you're using Xcode, you can always command-click a protocol that appears anywhere in your code to jump to the header where that protocol is defined. This is true even of Apple's protocols, since header files are not compiled. Also, the documentation available through Xcode provides additional insight on what methods are required or optional.
Since you can define optional protocol methods, you should always check to see if your delegate -respondsToSelector:#selector(isThisMethodImplemented:), since the language doesn't do this for you.
Also, if you're using Xcode, you can option-click a class in your code to bring up the quick documentation panel, which has an option to go to the full documentation for the class of the object you clicked on.
You can either look at the documentation or view the corresponding header file by Command-clicking the protocol in Xcode (Command-doubleclick in Xcode 3).
Check out the doc the delegate property, it is almost all the time defined is id type and which protocol it is conforming to : id <TheProtocolYouLookFor>.
If not, read down the description and you will find more information about the protocol. Protocol names are also links in general.

Delegate method seems to be #required where it's declared as #optional

I've created my own Delegate for a ObjC class. The class itself deals with Core Data operations. Delegate methods are used to inform other classes about changes that happened to the datastore. The class that deals with the datastore is called Datastore and it's delegate is called DatastoreDelegate. A UIViewController of mine (ContactsViewController) implements the delegate.
My DatastoreDelegate is declared as followed:
#class Datastore;
#protocol DatastoreDelegate <NSObject>;
#optional
- (void)didAddMessage:(Message *)message;
- (void)didUpdateContact:(Contact *)contact;
- (void)didAddContact:(Contact *)contact;
- (void)didUpdateContact:(Contact *)contact;
- (void)didDeleteContacts;
#end
The weird thing is, my code all worked fine with these methods except for the [didAddMessage:] method. Whenever I try to call this delegate from within the Datastore class I get an error from the ContactsViewController. The error tells me the [didAddMessage:] selector is missing in the ContactsViewController instance (Unrecognized selector sent to instance). How can the selector be missing if it's optional?
I should note that my Datastore class is a Singleton. I'm not sure if this is somehow related to this issue I'm having.
"Optional" means the caller is responsible for checking that a target responds to a given selector. E.g.:
if ([_myDelegate respondsToSelector:#selector(didAddMessage:)])
{
[_myDelegate didAddMessage:theMessage];
}
Did you implement didAddMessage: in your ContactsViewController? It's optional so you aren't forced to implement it, but if you send the didAddMessage: message to ContactsViewController but haven't actually implemented it in ContactsViewController, you'll still get a compiler warning. In other words, #optional just means you don't have to implement it, but the compiler may still give a warning if you haven't implemented it but try to use it.
What you might want to do in Datastore is this:
if ([delegate respondsToSelector:#selector(didAddMessage:)]) {
[delegate didAddMessage:theMessage];
}
rather than just:
[delegate didAddMessage:theMessage];
(You'll still get a compiler warning in the first example, but it's safe to ignore since you're checking at runtime to see if the appropriate method is implemented in the delegate.)