callback-callback, in each programming language is a very important function, such as pop-up window a child control, in the child control to get information after the need to return data to the caller, the most mainstream approach is to pass the caller as a parameter to the child control, Then, when the child control gets the information, it passes the message to the caller before it comes in. In iOS, this is done in a way called delegate (proxy), which usually appears when you create a child control: a child control. Delegate = self, which means that I am the proxy for this child control, and when the child control needs a callback, Just call its member delegate (that is, me) and you can pass the message back.
However, in many cases such agents will be very ' verbose ', such as I just want to simply pop up a dialog box (Uialertview) and then know whether the user chooses OK or cancel, but to do two things on the caller, The first is to declare this dialog box protocol (Protocol) to be able to receive the dialog box callback eligibility, and then to implement callback methods, such as OnOK, OnCancel, and so on, more troublesome, if I have three dialogs here, it is necessary to implement a number of protocols to do their proxies.
So here you can use block to its closure, directly in the context of the declaration of the callback, not only not to increase the callback method, but also easily solve the complex situation of multiple callbacks. Now take Uialertview for an example:
Normal practice: Callers summon Alertview at the same time, their agents point to themselves: Alertview.delegate = self; Then, when the user taps the button on the dialog box, it triggers its callback method (if its proxy exists, it will not be called if there is no declaration pointing):
Called when a button is clicked. The view'll be automatically dismissed after this call returns
-(void) Alertview: (uialertview*) Alertview clickedbuttonatindex: (nsinteger) buttonindex;
The optimization idea here is:
Modify the Uialertview class, add a block object, and then let it do its own delegate, the caller will be the block as a parameter, in its own Clickedbuttonatindex method call block.
Specific implementation:
1. Create the Uialertview class extension, uialertview+block;
2. Declare a callback block:
typedefvoid (^uialertviewcompletionblock) (uialertview *alertview,nsinteger Buttonindex);
3. Add the interface to pass in the block.
+ (instancetype) Showwithtitle: (nsstring *) title
Message: (nsstring *) message
Style: (uialertviewstyle) style
Cancelbuttontitle: (nsstring *) cancelbuttontitle
Otherbuttontitles: (nsarray *) otherbuttontitles
Tapblock: (uialertviewcompletionblock) tapblock;
4. When setting Tapblock, modify the object, add the member variable, here is the core:
Objc_setassociatedobject(self,uialertviewtapblockkey, Tapblock,objc_association_copy );
*uialertviewtapblockkey is not a string, is a void*, and Tapblock form a k-v unique pairing, to a Uialertview check key, you can get Tapblock as value return. The setassociatedobject here is the runtime programming API, so you need to #import<objc/runtime.h>
At this point, the tapblock has been implanted into the object Uialertview and can be obtained in key-value way.
5. Point the agent to yourself
Self. Delegate = (ID<uialertviewdelegate>)self;
6. Implement Proxy Method -(void) Alertview: (uialertview *) Alertview clickedbuttonatindex: (nsinteger) Buttonindex, in which the implanted tabblock is called.
Finish the call.
Run-time programming joins the block