Every application contains many loosely coupled objects. What communication mode is used for interaction between them? Which communication mechanism is the best practice? These are all questions worth thinking about (although there are no clear answers, there are also some conventional usage habits ).
Generally, we can use the following communication modes: KVO, Notifications, delegation, blocks, and target-action.
1. Understanding about Communication Patterns
1. KVO
The KVO mechanism is used to notify the changes of object attributes.
The Message Receiver --> receives a message whose object attributes change; the message sender --> the object attributes change.
The message receiver registers a listener to the message sender and must know the life cycle of the message sender to cancel registration.
2. Communications
Notifications are used to broadcast messages between codes.
Notifications send arbitrary messages. You can use the userInfo dictionary or the NSNotification message carrier to load the sent messages.
With Notifications, message senders and receivers can communicate with each other, that is, messages are transmitted between loosely coupled codes. In addition, this is a one-way communication method, that is, the receiver cannot reply to Notifications of Notifications.
3. Delegation)
The role of delegation is to pass values and to upload events.
Define any required delegate methods in the delegate protocol to process communication between two specific objects. The sender is the delegate. In the delegate protocol, the delegate method is defined. The receiver is the delegate, and the delegate method in the delegate protocol is implemented.
4. Blocks
Blocks is usually used for callback event processing and so on. It is a relatively new technology. Generally, block can meet the message transmission mechanism implemented by delegation. However, these two mechanisms have their own characteristics.
Potential Risk: retain cycle.Because all variables referenced by blocks are automatically retained once, if the referenced variables cannot be set to nil, the use of Blocks will show the retain cycles.
For example:
DoSomethingManager *manager = [[DoSomethingManager alloc] init];manager.complete = ^{ //...complete actions [manager otherAction]; [manager release];};
In this example, because the manager and the block hold each other, a retain cycle is formed even if the release is called.
To remove the retain cycle, modify the code:
DoSomethingManager *manager = [[DoSomethingManager alloc] init];manager.complete = ^{ //...complete actions [manager otherAction]; manager.complete = nil; [manager release];};
Because manager. complete = nil breaks the retain cycle.
Let's look at an example of NSOperation:
self.queue = [[NSOperationQueue alloc] init];MyOperation *operation = [[MyOperation alloc] init];operation.completionBlock = ^{ [self finishedOperation];};[self.queue addOperation:operation];
At first glance, there seems to be a retain cycle:
Self-- Retain -->
Queue-- Retain -->
Operation-- Retain -->
Blcok-- Retain -->
Self
However, after an operation is added to the queue, the execution will end at a certain time point and then exit the queue. Once the operation exits the queue, the retain cycle will be broken.
5. Target-Action
Target-Action is a typical mode for sending messages in response to UI events.
The target for timely message response is nil empty, and the action will also followResponder chain(Response chain) locate an object to respond.
Target-ActionRestrictionsMessage sending cannot carry any custom load messages.
Ii. Making the Right Choice
Based on the features of the above communication mode, the following flowchart is constructed to help you make the right decision on which mode to choose. (The suggestion in this figure is not necessarily the final answer)
Iii. Framework Examples
1. KVO
NSOperationQueue uses the KVO mechanism to observe operation state attribute changes (isFinished, isExecuting, isCancelled). When operation state attribute changes, NSOperationQueue will receive a KVO Message notification.
NSOperationQueue -- Message Receiver
Operation -- message sender
Obviously, the two require a one-way communication mechanism, and NSOperationQueue is only interested in changes in the state attribute of the operation object. Therefore, KVO is the best practice.
It is true that KVO is a very good practice. Of course, it seems that Delegation can also be used.
Operation queue is the operator's delegate (delegation). operation can call delegate protocol methods such as operationDidFinish or operationDidBeginExecuting to notify operation queue of changes in operation state attributes.
2. Communications
Core Data uses notification to communicate between events, for example, managed object context (NSManagedObjectContextDidChangeNotification)
For a change notification sent by the managed object context, the Message Receiver does not have to know who is the sender, and this is not a UI event, so the receiver can have multiple. It indicates that a one-way communication pipeline is needed, and communications is the only choice.
3. Delegation
The implementation of Table View adopts Delegation. For example, tableView: didSelectRowAtIndexPath: method. Why is it implemented by calling delegate? Why not use the target-action method?
As we can see in the flowchart, custom data cannot be transmitted when target-action is used. When selecting a cell in the table view, the collection view not only needs to tell us that a cell is selected, but also to tell us which cell is selected (index path ). According to this idea, we can see from the flowchart that the delegation mechanism should be used.
4. Blocks
For more information about block, see [NSURLSession dataTaskWithURL: completionHandler. How does one transmit messages from the URL loading system to the caller? First, as the caller of this API, we know the sender of the message, but we do not have the sender. In addition, this is a one-way message transmission-directly calling dataTaskWithURL: method. If we follow these steps to compare the flowchart, we will find that the block-based message transmission mechanism should be used.
Are there other optional mechanisms? Of course, Apple's NSURLConnection is the best example. NSURLConnection already exists before the advent of block, so it does not use block for message transmission, but uses the delegation mechanism. When the block appears, Apple adds the sendAsynchronousRequest: queue: completionHandler: method (OSX 10.7 iOS 5) to NSURLConnection. Therefore, if it is a simple task, you do not need to use delegate.
In OS X 10.9 and iOS 7, Apple introduced a very modern API: NSURLSession, where block is used as the message transmission mechanism (NSURLSession still has a delegate, but it is used for other purposes ).
5. Target-Action
The most obvious use of Target-Action is the button ). In addition to sending a click event, a button does not need to send any other information. Therefore, Target-Action is the best choice in the process of passing User Interface events.
If the taget parameter is specified, the action message is sent back to the specified object. If taget is nil, the action message will find an object that can process the message in the response chain in a bubble mode. At this point, we have a completely decoupled message transmission mechanism-the sender does not need to know the receiver, and some other information.
Target-Action is very suitable for events on the user interface. Currently, no other suitable message transmission mechanism can provide the same function. Although notification is the closest to this Decoupling Relationship Between the sender and the receiver, target-action can be used in the responder chain-only one object obtains the action and responds to it, in addition, an action can be passed in the response chain until an object that can respond to the action is encountered.
Iv. Summary
The communication modes used for message transmission between two objects are sometimes ambiguous. However, when you carefully consider them, you will find their respective needs and features.
The decision-making flow chart provided in the article is only a reference for selection. It is not the final answer. Practice is a good idea!
Note: This article is originated from the objc. io Article Communication Patterns. Full-text translation: message transmission mechanism in iOS