Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 586
Wolfgang Schreurs Avatar asked Jan 30 '10 19:01

Wolfgang Schreurs


People also ask

How do you call a delegate method in Objective-C?

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.

How do I make a delegate optional in Swift?

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.

How do I declare Optional protocol in swift 5?

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.

How do you declare a protocol in Objective-C?

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.


2 Answers

"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];
}
like image 59
Darren Avatar answered Oct 15 '22 19:10

Darren


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.)

like image 34
mipadi Avatar answered Oct 15 '22 18:10

mipadi