The main content of this article
- Understand what a block is.
- Learn how block is used.
Block is the new program syntax for iOS after version 4.0.
After iOS SDK 4.0, block appears in almost all new versions of the API, in other words, if you do not understand the concept of block is not able to use the new version of SDK 4.0, so although the syntax of the block itself is a bit difficult, But in order to use the new features of iOS we have to bite the bullet to understand the new program concept.
First, take a look at what is block
We use the ' ^ ' operator to declare a block variable, and after declaring a block variable, it is like declaring a normal variable, and finally adding '; '.
Next, we use an example to declare a simple block variable.
int int ) = NULL;
Let's take a look at the syntax for declaring a block variable
Data return value type (^ variable name ) (parameter list) = NULL;
Next, we assign a value to the block variable just now.
block = ^ (int m) { return m * m;};
And then we'll use the block variable once.
// by using the block variable, the square of the integer constant 10 is computed and printed on the controller output NSLog (@ "10 squared is:%d", Block (ten));
Note that by now we should have found the use steps of the block variable, there are steps similar to the function
- The first is to declare (declare the function, declare the block variable);
- It is then implemented (implementing the function, assigning the value of the block variable to the implementation process);
- The final call is required to achieve the specific function
Second, take a look at how to directly use the block parameter
Array sorting
//declaring an array variableNsmutablearray *mutablearray = [[Nsmutablearray alloc] Initwithobjects:@"5",@"2",@"3",@"9",@"7", nil]; //Array Ascending order using block directly[Mutablearray Sortusingcomparator:^nscomparisonresult (IDObj1,IDobj2) { //An object that converts two parameters to a stringNSString *value1 = (NSString *) obj1; NSString*value2 = (NSString *) Obj2; //value1 and value2 two objects are returned directly return[value1 compare:value2]; }]; //printing variable array variablesNSLog (@"%@", Mutablearray);
A Simple network asynchronous request
//declaring a network Address objectNsurl *url = [Nsurl urlwithstring:@"http://www.qq.com"]; //declares a network request object based on the network address objectNsurlrequest *request =[Nsurlrequest Requestwithurl:url]; //use the block variable directly to complete the data return function after successful link[Nsurlconnection sendasynchronousrequest:request queue:[nsoperationqueue Mainqueue] completionHandler:^ ( Nsurlresponse *response, NSData *data, Nserror *connectionerror) { //converting binary data to string objects using UTF8 encodingNSString *result =[[NSString alloc] Initwithdata:data encoding:nsutf8stringencoding]; //results after the print link is completeNSLog (@"%@", result); }];
You can see that many of the features in the iOS platform have been integrated with the block syntax approach.
Third, take a look at the block syntax in-depth understanding
In this section, the main thing to introduce is the use of __block modified variables to accomplish the function.
Let's look at an example first.
// declares a local integer variable int intvalue = 3 // declares a block variable with a return value of int, an int parameter int (^block) (int ) = ^ (int m) { return m * Intvalue; }; // call the block variable, 5 as the result of the parameter NSLog ( Span style= "color: #800000;" >@ " block (5) =%d " , block (5 ));
In the example above, we refer to the Intvalue variable as an external variable during block execution, which can be used directly during block execution.
Let's look at an example.
// declares a local integer variable int intvalue = 3 // declares a block variable with a return value of int, an int parameter int (^block) (int ) = ^ (int m) {intvalue ++; return m * Intvalue; }; // call the block variable, 5 as the result of the parameter NSLog ( Span style= "color: #800000;" >@ " block (5) =%d " , block (5 ));
In the example above, we compile the program and find that the compiler has a red error , and the error message is
Variable is not assignable (missing __block type specifier)
Why is there an error message that cannot be assigned?
When the block is implemented, it makes a read-only copy of the stack variable defined in the method it refers to, and then uses that read-only copy within the block blocks.
To avoid the above error, use the __block modifier to modify the external variable to inform the compiler that the external variable intvalue and the Intvalue in the block refer to the same memory address, without the need for a memory copy. The following example
//Modifying a intvalue local integer variable with the __block modifier__blockintIntvalue =3; //declares a block variable that returns a value of int, an int parameter int(^block) (int) = ^(intm) {Intvalue++; returnM *Intvalue; }; //Call the block variable, 5 as the result of the argumentNSLog (@"block (5) =%d", Block (5));
Iv. memory issues to be aware of using block
Use Weak–strong Dance technology to avoid circular references
Examples are as follows
////VIEWCONTROLLER.M////Created by Lewis.//#import "ViewController.h"@interfaceViewcontroller ()@end@implementationviewcontroller{IDObserver;}- (void) viewdidload{[Super Viewdidload]; //add observer, observe topic Modify message notification, and after receiving a message notification, print the View Controller objectObserver = [[Nsnotificationcenter defaultcenter] Addobserverforname:@"kthemechangenotification" Object: Nil Queue:[nsoperationqueue Mainqueue] usingblock:^ (nsnotification *Note) {NSLog (@"%@", self); }];}- (void) didreceivememorywarning{[Super didreceivememorywarning]; //Dispose of any resources the can be recreated.}//when the view controller object is destroyed, remove the viewer- (void) dealloc{if(Observer) {[[Nsnotificationcenter defaultcenter] removeobserver:observer]; }}@end
In the code above, we add an observer to the notification hub and then release the registration at Dealloc, and everything looks normal. But here are two questions:
- In the message notification block refers to self, where the Self object is block retain, and Observer retain a copy of the block, Notification Center and hold observer. So as long as the Observer object has not been de-registered, the block will be held by the Notification center, so that self will not be freed and its dealloc will not be invoked. And we expect to removeobserver in Dealloc to remove the notification center from the Observer/block retain.
- At the same time, observer is defined as an assignment in the Self's class, so it is retain by self, thus forming a circular reference.
The solution is as follows.
////VIEWCONTROLLER.M////Created by Lewis.//#import "ViewController.h"@interfaceViewcontroller ()@end@implementationviewcontroller{IDObserver;}- (void) viewdidload{[Super Viewdidload]; //declare a weak weak object first__weak Viewcontroller *wself =Self ; //add observer, observe topic Modify message notification, and after receiving a message notification, print the View Controller objectObserver = [[Nsnotificationcenter defaultcenter] Addobserverforname:@"kthemechangenotification" Object: Nil Queue:[nsoperationqueue Mainqueue] usingblock:^ (nsnotification *Note) { //use strong objects to reference weak objects during block executionViewcontroller *bself =wself; if(bself) {NSLog (@"%@", bself); } }];}- (void) didreceivememorywarning{[Super didreceivememorywarning]; //Dispose of any resources the can be recreated.}//when the view controller object is destroyed, remove the viewer- (void) dealloc{if(Observer) {[[Nsnotificationcenter defaultcenter] removeobserver:observer]; }}@end
First, a weak reference to self is defined before the block wself, because it is a weak reference, so wself becomes nil when Self is freed, and then references the weak application in the block, considering the multithreaded case, by using a strong reference bself to reference the weak reference, as If self is not nil, self is retain to prevent self from being freed during subsequent use, and the strong reference sself is then used in subsequent block blocks, noting that the bself is nil-detected before use because a weak reference to wSe in a multithreaded environment LF The bself is assigned a strong reference, the weak reference wself may already be nil. Through thisWeak-strongMethod, the block will not hold the self reference, thus breaking the circular reference.