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.
To create one, you define a class that implements the delegate methods you're interested in, and mark that class as implementing the delegate protocol. Then you could create an instance of MyClass and assign it as the web view's delegate: MyClass *instanceOfMyClass = [[MyClass alloc] init]; myWebView.
Set the delegate to a class and implement the Protocol. See that the optional method does not need to be implemented. One important thing is that the optional method is optional and needs a "?" when calling. Mention the second question mark.
Swift protocols on their side do not allow optional methods. But if you are making an app for macOS, iOS, tvOS or watchOS you can add the @objc keyword at the beginning of the implementation of your protocol and add @objc follow by optional keyword before each methods you want to be optional.
In Objective-C, protocols are declared with the “@protocol” keyword. Below is an example of declaring a protocol containing one required method. In Swift, the syntax is a little different but the idea is the same. In Objective-C, you add the protocol name in angle brackets beside the class interface declaration.
"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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With