iOS communication mode (KVO, Notification, Delegate, Block, target-action differences)

Source: Internet
Author: User


Articles translated from https://www.objc.io/issues/7-foundation/communication-patterns/


Each application, more or less, consists of loosely coupled objects (modules) that must communicate with each other to complete their work. This article will use the communication mechanisms available and give an example of the Apple framework and provide the best practice recommendations on which communication mechanisms are used.

Although this issue is about the foundation framework, we can use the communication mechanism of foundation, there are almost these communication methods-kvo,notification,delegate,block,target-action.

Of course, no one defines the type of pattern that must be used in which case, and the choice is often a personal taste. But there are a lot of things that can be very clear about which communication mechanism to use.

In this article, we often use ' recipient ' (receiver) and ' sender ' (sender), for example: TableView is a sender, its agent is recipient. The Core data managed object is sender, and the object that he receives by sending a notification is recipient. Slider is sender, its action implement is recipient, an object if you listen to a property with KVO, then the property change is a Sender,observe is recipient. Do you understand?

communication Mode in iOS

First we look at the different points of each communication pattern. Based on this, we help you choose which mode to use through the flowchart. Finally, let's take a few examples from Apple's framework.


KVO

KVO is a mechanism for notifying object property changes, and the foundation and many other implementations of Apple's framework rely on it. If you want to know more about the use of KVO, please click this link.

If you are interested in changing the properties of an object, it is appropriate to use KVO. It has some requirements, first of all, that your recipient (receiver) needs to listen for a message about a property change from sender, and sender will tell you the value after the property has changed. In addition, recipient also needs to know the sender's life cycle, because the listener needs to be logged out before sender calls Dealloc. If the above conditions are met, then it is appropriate to use KVO. KVO can even be one-to-many and can set up multiple listeners at the same time.

If you want to use KVO in a CoreData object, it will be a little different, which is related to its faulting mechanism. When a CoreData Manager object enters the faulting, he also notifies the observer that their attributes have not changed.


Notification

Notification is a great tool to broadcast messages between two unrelated objects, especially when there is a companion message, and you don't need to do anything else.

Notifications is used to send any message, and when you use the Nsnotification subclass, you can also attach a custom parameter to the dictionary of UserInfo. Notifications is the only communication mechanism that makes sender and recipient do not need to know each other. Also more loosely coupled. So this mechanism is one-way-you can't reply to a notification (do something to sender).

The delegate pattern is widely used in Apple's framework, which allows you to customize the behavior of an object and notify it to execute at some point. In delegate, sender needs to know about recipient, but it is more loosely coupled than the usual way, because sender only knows that his delegate has complied with a protocol.

Because you can define any method in protocol, you can create exactly the communication pattern you want, you can pass the custom data in the parameter, and can respond to the return value. Delegate is a flexible and simple way, if you just need to communicate between two objects, it's a relatively close relationship between two objects.

Excessive use of the delegate mode is also dangerous, if two objects are tightly coupled, and one cannot have no other, it is not appropriate to use delegate. In this case, an object should be set directly to the properties of another object. For example: Uicollectionviewlayout and Nsurlsessionconfiguration.


Blocks

The block was added to OS X 10.6 and iOS 4. Blocks replaces many of the places previously implemented in delegate mode. However, both of these models have their own pros and cons.

If you are using block. If your sender needs to refer to block, but there is no guarantee that the reference will be nil, and if the self is used in bloc, a circular reference is generated. Let's say we don't need to delegate and use block to implement a tableveiw, like this:

self.myTableView.selectionHandler = ^void(NSIndexPath *selectedIndexPath) {    ...};

The problem here is that self refers to the Tableview,tableview Application block in order to use it at some point in the future. TableView don't know when to set him to nil. If we cannot guarantee that a circular reference will break at some point, the block will not be suitable for use in this case.

There is no such problem with nsoperation. Because he will break the circular reference at some point.

 Self.Queue = [[Nsoperationqueue Alloc]Init]; Myoperation *operation =[[Myoperation Alloc]Init];operation.completionblock = ^{[ SelfFinishedoperation];};[ Self.QueueAddoperation:operation];

At first glance, there seems to be a circular reference, and self refers to the Queue,queue reference to Operation,operation, which references the complete block,complete block. However, when operation is added to the queue, operation executes, and the queue will remove the operation when the execution is complete, which breaks the circular reference.

Another example: Suppose we go to implement a video encoding class (Encoder Class), we call the Encodewithcompletionhandler: method. In order to make the call problem-free, we must ensure that the encoded object resets the block reference to nil at some point. Like this:

 @interface Encoder ()@property(nonatomic, copy)void(^completionhandler) ();@end @implementation Encoder - (void) Encodewithcompletionhandler: (void(^) ()) handler{ Self. Completionhandler= handler;//Do the asynchronous processing ...}// This one'll be called once the job was done- (void) finishedencoding{ Self. Completionhandler(); Self. Completionhandler=Nil;//<-Don ' t forget this!}@end

Once we have called complete block, we immediately put him as nil.

Block is perfect for a single callback, because we know when to break the reference loop in this case. In addition, block readability is better because method invocations and processing are together. Along this line, blocks are suitable for use in Completehandler and ErrorHandler cases.


target-action

Target-action is a pattern used in response to user UI actions. Support for this mode on iOS is Uicontrol,mac on nscontrol, Nscell. Target-action establishes a loosely coupled relationship between sender and recipient. Recipient do not need to know sender,sender nor need to know recipient. In the case where target is nil, the action enters the event response chain, knowing that an object can be found to respond to it. In iOS, a control can correlate multiple target-action.

The limitation of using the Target-action mode is that you cannot pass custom parameters. Sender is always the first parameter on a Mac. In iOS you can select sender and event mode as arguments to the action. However, there is no way to pass other objects.


How to choose the right pattern

Based on the different characteristics of each pattern mentioned above, we draw a flowchart to help you choose when to use which mode. But it is only a suggestion, not the final answer. You might as well have done the other choices. But at work, in most cases, you are guided to make the right choices.

Some of the details in the picture need to be explained:

There is a "sender is KVO compliant" in the picture, not only that he can send the message when the property changes, but also that the observer must know the sender's life cycle. If sender is saved as a weak reference, it may be released at any time, which will result in a memory leak.

There is also a sentence of ' message is direct response to method call ', which means that the receiver of the method invocation must callback the caller's method as a direct response to it. You can also understand that it makes sense for your calling code and handling code to appear in the same place.

Finally, you should also consider whether sender can make sure that block is set to nil at some point, and if not, a circular reference may be generated.


Framework Case

Next, we have some examples of the Apple framework to illustrate the above flowchart is reasonable, why Apple chose to use this model.


KVO

Nsoperationqueue internally uses KVO to monitor the status changes of each operation (isfinished, isexecuting, iscancelled). When the status changes, the queue receives a KVO notification. Why Nsoperationqueue use KVO?

Because recipient (nsoperationqueue) knows the sender (Nsoperation) clearly and controls their life cycle. Further, this use only requires one-way communication. If Nsoperationqueue is only interested in changing the attribute value of nsoperation, there is no need to use KVO necessarily. But we can at least say that the value change is modeled as a state change. Because the nsoperationqueue needs to nsoperation the State property at all-the-latest status. It is logical to use KVO in this case.

KVO is not the only option. We can imagine that nsoperationqueue becomes an agent for Nsoperation, and then nsoperation internally calls something like Operationdidfinish: or operationdidbeginexecuting: The Nsoperationqueue statement notifies the state of the change. This is inconvenient, and in order to keep the nsoperation state up to date, you must add the code.


Notifications

CoreData uses the notification mechanism to communicate (nsmanagedobjectcontextobjectsdidchangenotification) When the context of the managed object changes.

This notification is sent by the contexts of the managed object, so we cannot let the recipient of the message know who the sender is. Since the origin of the message is obviously not a UI event, multiple receivers may be interested in it, and they must be a one-way channel, then the only choice when using notification.


Delegate

TableView's delegate can be implemented in a variety of functions, from views that manage editing state to cells on the tracking screen. For example, we know Tableview:didselectrowatindexpath: This method, why do we use delegate to achieve? Why not use Target-action mode to implement?

As we have already mentioned in the chart above, Target-action is only used in cases where we do not need to send a reference. If a selected event occurs, then CollectionView not only tells us that a cell check event has occurred, but also tells us the Indexpath of the selected cell. If we are going to pass the Indexpath parameter, we can find the use of delegate mode along the image.

If we do not transfer the Indexpath parameter to the chosen method, instead of accessing the tableview to get the cell selected, it is inconvenient, in terms of the function of multiple options, And then we have to manage which cells are selected in order to tell which cell was last selected.

Similarly, we can imagine the use of notifications and KVO implementations.
In any case, you will encounter the above-mentioned problem. In addition to our own management, we can not distinguish which cell is the last selected/unchecked.


Block

Based on the block call we take-[nsurlsession Datataskwithurl:completionhandler:] For example, when the call Fanga to download a URL, how is it callback? First, as the caller of this API, we know when to send a message, but we can't reference it. Or, this is a one-way communication directly coupled Datataskwithurl: Method invocation. If we control the image above, we will find the way to use block.

Do you have any other options? Of course, Apple's own nsurlconnection is a good example. Nsurlconnection existed before the block appeared, so they used delegate mode to do it. Once the block appears, Apple adds MethodsendAsynchronousRequest:queue:completionHandler to nsurlconnectionin on OS X 10.7 and IOS 5: method to achieve a simple task.

Because Nsurlsession's API appears after OS X 10.9 and IOS 7, block is used as the type of communication (Nsurlsession still has delegate, but in other ways).


target-action

The most obvious example of using Target-action mode is buttons, which does not need to pass any other information except when they are clicked. Therefore, the target-action mode is best suited for handling user interface events.

If target is specified, the action message is sent directly to the target object. However, if Target is nil,action, it goes into the event response chain to find which object can handle it. When the sender does not need to know the recipient, we have a completely decoupled communication mechanism.

Target-action This mode is perfect for user interface events. No other communication mode can provide the same functionality. The notifications can also be fully decoupled from the sender and receiver, but it does not have a Target-action event response chain mechanism.



Conclusion

There are so many communication modes available in the communication mechanism that we are happy. However, the choice of which mode is often blurred in use. Once we study each pattern carefully, we find that they all have their own characteristics.

iOS communication mode (difference between KVO, Notification, Delegate, Block, target-action)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.