In my iOS app, I have a lot of places where I show a modal view, and that view needs to have access to the view that opened it. To implement this connection, I’m using the concept of “delegates,” where one object has another object that it can call methods on. I created a protocol called ModalDelegate that defined the methods that these modals could call on their parent views. However, the way I implemented this caused a lot of compiler warnings. I just now figured out how to fix these, but the answers were difficult for me to find, so I figured I’d post them here.
First, it was my understanding that using
id as a variable type was the standard Objective-C way to keep a reference to an object that can be of any class–the equivalent of the Java class Object, but more widespread in use. However, when I stored my delegate as an
id, then tried to call a method on it, I received a warning that that method might not be defined. I could have cast the id to the appropriate type, but that seemed like it shouldn’t be necessary.
So, instead, I changed the type of the variable from
ModalDelegate, the name of the protocol I created. This seemed intuitive to me from the way Java interfaces are used, and the compiler didn’t reject that variable naming. However, I got a similar warning: that method might not be defined. When I looked into it, I discovered that wasn’t the right syntax to use for a protocol at all. The right type for the variable was
id <ModalDelegate>–in other words, an object of any type, but one that conforms to the ModalDelegate protocol. Also, instead of referring to
@class ModalDelegate; in my header file, I needed to refer to
The one remaining warning I was getting after this was that my classes weren’t implementing all the methods on the ModalDelegate protocol. The reason for this was that different views needed to have different methods called on them, and I didn’t want to have a separate delegate definition for each. So there were lots of methods in ModalDelegate, and each class that conformed to the protocol only implemented some of them. Of course, this isn’t how protocols are meant to work, but I didn’t see an alternative. But finally I found it: optional methods on protocols. I just add an
@optional above all the methods that I want to be optional, and then the warnings went away. For my protocol, I actually wanted all the methods to be optional.
I don’t think this is a violation of the concept of the protocol, precisely because it removes all the warnings I had above. My modal view can call methods on its delegate without compiler warnings, because it knows it should have an id and that it may have a method of the appropriate type. The alternative would be to simply have an
id and accept the warnings, or else use performSelector:withObject:, but those seem like overkill for the situation I’m in. The other alternative would be to implement each of the protocol methods and leave some of them as empty implementations. But all of these seem like overkill for my situation. With a protocol with optional methods, I’ve clearly defined for the compiler what I’m doing, and its lack of warnings assures me that I don’t have any typos.