How do I solve the multiple callback problem for the same delegate in Objective-C?

I created a library that can load JSON data, which is then placed in an NSDictionary. I wrap this class with a simple Twitter engine that allows me to pull out the timelines of my friends, post an update and post an update with my GPS location. From my limited experience with Objective-C, the way to connect to everything is related to delegation. I set a delegate property that returns an asynchronous result to either the selector or the method. I can even create an optional or required interface for the delegate that will allow Xcode to help me a bit in implementing delegation. To learn about using delegates in Objective-C, I created this simple project.

http://www.smallsharptools.com/downloads/ObjC/Delegates.zip

It defines a Worker class that allows you to initialize a class with a delegate. When work is done using the doWork method, it looks for the method signature in the delegate to send the message back to. It uses the following code.

if([[self delegate] respondsToSelector:@selector(workFinished:)]) { NSString *msg = @"That it? Easy!"; [[self delegate] workFinished:msg]; } 

He is looking for the workFinished: method to send a message. I declared this method signature as an optional interface with the following code in the header, Worker.h.

  @protocol WorkerNotifications @optional - (void) workFinished: (NSString *) msg; @end 

You can see the rest of the project from the download for all the details. But these 2 code snippets show how this delegation pattern works. But with the Twitter class, I need to know the context of the method that triggered the asynchronous action, which results in a callback to the delegate method. If I call the sendUpdate method more than once from the calling class, how should I know the callback context?

Usually with a language like JavaScript, Java or C #, I would create a built-in closing or anonymous class that would have access to the original context, but this is not currently possible with Objective-C on the iPhone. I found that this question has already been asked and answered StackOverflow.

Anonymous delegate implementation in Objective-C?

So, I did skip the optional interface and instead passed it to the selector, which the Twitter class will call when the asynchronous action is completed. The call to start this action is as follows:

 CMTwitterEngine *engine = [[CMTwitterEngine alloc] initWithDelegate:self]; [engine setSendUpdateFinished:@selector(sendUpdateFinished:)]; [engine setSendUpdateFailed:@selector(sendUpdateFailed:)]; [engine setParsingSendUpdateFailed:@selector(parsingSendUpdateFailed:)]; [engine setUsername:TWITTER_USERNAME pass:TWITTER_PASSWORD]; [engine sendUpdate:statusUpdateText.text]; 

This code first initializes a link to the engine using self as a delegate. To attach callbacks, I send in selectors that I originally used on the signature of the sendUpdate method, but the method calls are quite long. I decided to just set the properties of the selectors. It all works, but I'm not sure I like the way it works, since it only partially solves my problem.

To complete this example, I end the asynchronous operation and end up calling the method inside, which searches for the given selector and calls it if one is defined.

 - (void)sendUpdateFinished:(NSDictionary *)dictionary { if (self.sendUpdateFinished != nil) { [self.delegate performSelector:self.sendUpdateFinished withObject:dictionary]; } } 

I can send the status message for sending as a Twitter update, but I still do not have the context of the outgoing call. What if I want to call sendUpdate more than once and the first asynchronous call is still running? But what if the second call ends first? Both of them will act as a delegate, so I will either have to track the context in some way, or pass them to another selector to distinguish them, which also does not satisfy my needs. What happens if I have 3 or 4 or 5 asynchronous calls? I need to know which of them were sent successfully and when they were completed.

It seems the only way I can do this is to create a class that contains all the properties necessary for the context, include this class as a delegate to call the asynchronous Twitter method, and then report back to the parent class, which is most likely the UIViewController . I would take this approach, but I have not read about this approach or have I seen any example code that does this.

What would you do? How would you deal with several asynchronous calls that could end in a different order than going out and then processing them with context after completion?

+4
source share
3 answers

I have a second (or third) previously posted answer that NSNotificationCenter is probably what you are looking for here.

Essentially, notifications are usually used when there are potentially many delegates, all of whom must do something in response to one action or event that happened. Think of it as a one-to-many affair or implementation of an observer pattern. Key things to know:

  • NSNotifications has a name that you define, which is only an NSString. Notifications can be published by name and subject to receive notifications by name.

  • When a notification is sent, a notificationSender object and / or a dictionary of user information may be provided. A notification is a direct way to determine who sent this notification when it is processed by the recipient. UserInfo is an NSDictionary that can be used to provide additional context information along with a notification.

So, instead of forcing all workers to accept the unofficial protocol and tinker with methods to invoke the reflection style, at run time you simply register worker instances with NSNotificationCenter. Normally, NSNotificationCenter registration is done in the init method of each work class. Instances of each type of worker are then usually set as โ€œfrozenโ€ objects in the NIB, or can be programmed in the application delegate so that they are registered in the notification center at an early stage in the applicationโ€™s life.

When this happens, you send NSNotification to the NSNotificationCenter (which is essentially a singleton), and then everything else that registers to receive this type of notification will have a method that was specified to handle this type of notification. After that, these methods can then call the general method back to the sender (obtained by the method of the NSNotification object) to inform the sender that they have completed their work.

Once every known employee has verified the common sender method, they can continue to execute any exit code.

+2
source

One thing to keep in mind is to use notifications. Simplifies the code, pairs are less dense.

+1
source

Source: https://habr.com/ru/post/1300206/


All Articles