iOS Development-block memory management for external variables

Source: Internet
Author: User

Block memory management of external variables

Code blocks are commonly used in iOS for callbacks, and this article focuses on the management mechanism of block to external variables. We know that if a variable outside the block is to be used in a block, if the variable is a local variable, it must be declared as the __block type first. Why is it? This involves block memory management of external variables.

I. Basic data types

Let's look at the following test code:

Local variable-(void) localdatatest{    int localdata = +;    NSLog (@ "Localdata--%p", &localdata);    Int (^sum) () = ^ (int a,int b) {        NSLog (@ "Localdata--%p", &localdata);        Return localdata + A + b;    };    Localdata = 0;    int c = SUM (from);    NSLog (@ "localdatatest--c=%d", c);}

Printing results:

2015-03-21 12:04:11.161 test1[837:31981] Localdata--0xbfff4ed0

2015-03-21 12:04:11.162 test1[837:31981] Localdata--0x7c18bb44

2015-03-21 12:04:11.162 test1[837:31981] localdatatest--c = 103

Static variable-(void) staticdatatest{    static int staticdata = +;    NSLog (@ "Staticdata--%p", &staticdata);    Int (^sum) () = ^ (int a,int b) {        NSLog (@ "Staticdata--%p", &staticdata);        Return staticdata + A + b;    };    Staticdata = 0;    int c = SUM (from);    NSLog (@ "Staticdatatest--%d", c);}

Printing results:

2015-03-21 12:04:11.162 test1[837:31981] Staticdata--0xc7b8

2015-03-21 12:04:11.162 test1[837:31981] Staticdata--0xc7b8

2015-03-21 12:04:11.162 test1[837:31981] staticdatatest--3

global variable-(void) globaldatatest{    NSLog (@ "GlobalData--%p", &globaldata);    Int (^sum) () = ^ (int a,int b) {        NSLog (@ "GlobalData--%p", &globaldata);        Return globalData + A + b;    };    GlobalData = 0;    int c = SUM (from);    NSLog (@ "GlobalData--%d", c);}

Printing results:

2015-03-21 12:04:11.162 test1[837:31981] GlobalData--0xc7b4

2015-03-21 12:04:11.162 test1[837:31981] GlobalData--0xc7b4

2015-03-21 12:04:11.163 test1[837:31981] GlobalData--3

Block variable-(void) blockdatatest{    __block int blockdata = +;    NSLog (@ "Blockdata--%p", &blockdata);    Int (^sum) () = ^ (int a,int b) {        NSLog (@ "Blockdata--%p", &blockdata);        Return blockdata + A + b;    };    Blockdata = 0;    int c = SUM (from);    NSLog (@ "blockdatatest--c=%d", c);}

Printing results:

2015-03-21 12:04:11.163 test1[837:31981] Blockdata--0xbfff4ed8

2015-03-21 12:04:11.163 test1[837:31981] Blockdata--0x7c2411c0

2015-03-21 12:04:11.163 test1[837:31981] blockdatatest--c = 3

The above 4 code is a test of the local variables, static variables, global variables, and block variables used in the block respectively. The test results show:

The address of the variable in the block is not changed for the external variable used in the block, if it is a static type or a global type. Since the address of a static variable and a global variable is fixed, the block does not replicate the value of the variable at the time it is defined, but instead reads it directly from the memory in which it resides.

Looking at local (local) variables and block variables, the two addresses in the block changed, and the first reaction was that the block copied both types of variables at the time of definition (i.e., opening up new memory space), but the result of the sum () was different. In fact, not all of them have been copied:

For a local variable, the block replicates it at the time of definition, it is used as a constant in the block, its value is not affected by the outside, so in the test code, the value of Blockdata is always 100.

For the block variable, you can see that its address has changed, but Blockdata is affected by the outside world. This is because Blockdata is on the stack when defining the variable itself, and when the block is defined, the variable is not copied, but the compiler transfers it to the heap. This can be verified by the following code:

-(void) blockdatatest{    __block int blockdata = +;    NSLog (@ "Blockdata-%p", &blockdata);    Int (^sum) () = ^ (int a,int b) {        NSLog (@ "Blockdata-%p", &blockdata);        Return blockdata + A + b;    };    NSLog (@ "Blockdata-%p", &blockdata);    Blockdata = 0;    int c = SUM (from);    NSLog (@ "Blockdata--%d", c);}

Printing results:

2015-03-21 13:22:07.350 test1[1180:68166] Blockdata--0xbff47ed8

2015-03-21 13:22:07.350 test1[1180:68166] Blockdata--0x7c452680

2015-03-21 13:22:07.350 test1[1180:68166] Blockdata--0x7c452680

2015-03-21 13:22:07.350test1[1180:68166] Blockdata–3

Once you see the block definition, the Blockdata address changes. This will understand why the printed Blockdata value is 3.

Ii. Types of objects//Local object
-(void) localobjtest{    UILabel *localobj = [[UILabel alloc]init];    NSLog (@ "localobj adress--%p", & Localobj);    void (^test) () = ^{        NSLog (@ "localobj adress--%p", & Localobj);        NSLog (@ "Localobj--%@", localobj);    };    Localobj = nil;    Test ();}

Printing results:

2015-03-21 13:44:25.848 test1[1332:79267] localobj adress--0xbff7ced4

2015-03-21 13:44:25.848 test1[1332:79267] localobj adress--0x7b63f8b4

2015-03-21 13:44:25.848 test1[1332:79267] Localobj--<uilabel:0x7c8337a0; frame = (0 0; 0 0);

Static Object-(void) staticobjtest{    static UILabel *staticobj;    Staticobj = [[UILabel alloc]init];    NSLog (@ "staticobj adress--%p", & Staticobj);    void (^test) () = ^{        NSLog (@ "staticobj adress--%p", & Staticobj);        NSLog (@ "Staticobj--%@", staticobj);    };    Staticobj = nil;    Test ();}

Printing results:

2015-03-21 13:44:25.917 test1[1332:79267] staticobjadress--0x85a48

2015-03-21 13:44:25.917 test1[1332:79267] staticobjadress--0x85a48

2015-03-21 13:44:25.917 test1[1332:79267] staticobj-(NULL)

Global Object-(void) globalobjtest{    globalobj = [[UILabel alloc]init];    NSLog (@ "staticobj adress--%p", & Globalobj);    void (^test) () = ^{        NSLog (@ "globalobj adress--%p", & Globalobj);        NSLog (@ "Globalobj--%@", globalobj);    };    Globalobj = nil;    Test ();}

Printing results:

2015-03-21 13:44:25.917 test1[1332:79267] staticobjadress--0x85a4c

2015-03-21 13:44:25.917 test1[1332:79267] globalobjadress--0x85a4c

2015-03-21 13:44:25.917 test1[1332:79267] globalobj-(NULL)

Block Object-(void) blockobjtest{    __block UILabel *blockobj = [[UILabel alloc]init];    NSLog (@ "blockobj adress--%p", & Blockobj);    void (^test) () = ^{        NSLog (@ "blockobj adress--%p", & Blockobj);        NSLog (@ "Blockobj--%@", blockobj);    };    Blockobj = nil;    Test ();}

Printing results:

2015-03-21 13:44:25.917 test1[1332:79267] blockobj adress--0xbff7ced0

2015-03-21 13:44:25.918 test1[1332:79267] blockobj adress--0x7c835598

2015-03-21 13:44:25.918 test1[1332:79267] blockobj-(NULL)

Summary: From the test results can be seen

* For static object variables and global object variables, the address is also not fixed.

* for local (local) object variables, when the block is defined, the (pointer) variable is also copied, which is used as a (pointer) constant in the block and unaffected by the outside world.

* For block object variables, it is also possible to define blocks to transfer variables from the stack to the heap, which can be verified by the same method. Therefore, the block variable is externally affected, causing the output to be empty.

Third, circular reference

Block is a strong reference to any of these objects, if one of the objects with the same strong reference block, it will cause two objects to each other strong reference to each other, that is, circular reference, resulting in each other can not release who the embarrassing situation, also caused by the memory leak. The solution to this problem is to do weak reference processing of the object outside the block. Take self as an example:

Since self is a strong reference to a block, if self is needed in block, a circular reference is formed if self is not processed beforehand. This is done by adding a sentence to the block:

__weak typeof (self) weakself = self;

The function of this sentence is to recreate a self object of type weak, and block does not form a strong reference, that is, when referencing weakself, it does not retain, thus avoiding the occurrence of circular references.

__block typeof (self), weakself= self;    [Self methodthattakesablock:^ {        [weakself dosomething];  }

With ease of understanding, real arrows represent strong references, and virtual arrows represent weak references.




iOS Development-block memory management for external variables

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.