iOS memory management (OBJECTIVE-C)

Source: Internet
Author: User
Tags modifiers

In mobile app development, memory management is a very important topic due to the limitation of mobile device memory. Objective-c's memory management is not only a must-ask topic in the interview, but also a part of the Daily project development, which should be paid more attention to. For the author of the Java language to get started programming world developers, accustomed to the garbage collector automation management, for OC Reference counter management method, still need to spend effort to learn and use.

1. Arc and non-arc

OC memory management methods are divided into arc (automatic reference counting auto reference count) and non-arc mode. Apple released Automatic Reference counting (ARC) in Xcode 4.2, which eliminates the burden of manually executing reference counts for developers.

Currently, Xcode will recommend the default Arc method (Arc does have a great advantage) for new projects. Of course, if you have to use non-arc, you can modify the automatic reference counting option to No in build setting. If you introduce a non-arc code or a static library in an arc project, you need to set the corresponding resource in build phases to-fno-objc-ar; instead, the non-ARC project sets arc to use-FOBJC-ARC.

Arc and non-arc, literally, is whether auto, that is, the compiler to automatically implement reference counting, or the developer manually complete the addition and subtraction of reference counts. As we now often use the ARC mode to develop, arc greatly reduces our work on memory management, and even many of the starter developers are completely like Java applications, without the release of the control object. For OC, however, starting with Mac OS x10.8, garbage collector is obsolete and there is no such concept on iOS. The memory management of OC on iOS, which is essentially the management of reference counts, understands reference counting and is the core of iOS memory management.

2. Reference counting

If an object is not referenced by another object, it indicates that the object is no longer required and can be disposed. This is like people at a dinner table, if there are people at the table, it shows that the table can not be cleaned up; only when everyone is eating well and leaving, the number of users is less than 1, only to indicate that the table has been used, can be cleaned up. So the time the object is released is that the reference count for that memory is less than 1. The memory management method in OC is based on the management of reference counts.

In arc mode, the compiler completes the management of reference counts, and the developer does not need to manually add the reference count management code (which is not actually allowed), so the following is primarily explained by the way the reference count is managed by non-arc mode code.

1 initialization and release of objects

Object in OC needs to inherit from the unified parent class NSObject. For a NSObject life cycle, focus on the following methods:

    • Alloc
    • New
    • Copy
    • Mutablecopy
    • Dealloc

When the first four methods are called, a new object is generated, and the reference count of object is +1, which is owned by the caller (that is, it needs to be freed by the caller). The system object and all objects in the library follow this rule, that is, all methods starting with the four method names above will make reference count +1; Conversely, all return object methods that do not start with the name do not have a reference count of +1. For arc, this rule is established as a mandatory requirement. When we customize objects ourselves, we should also follow this specification, although it is strange to use naming conventions to embody the way memory is managed.

Dealloc is an implementation method inside an object that is called when object has a reference count of 0, which is not referenced by another object, releasing object. It is important to note that Dealloc is called only once for each object's life cycle. However, when the reference count is 0 o'clock, there is no guarantee when the system executes the method. When the runtime system calls Dealloc, you should never call Dealloc manually, once the object is not available after the call.

In the Dealloc method of non-arc objects, the main thing is to release the reference that the object has, in addition, it is usually necessary to clean up the original configured observation behavior, such as remove KVO and notification observers. For Arc mode, we are not allowed to directly replicate dealloc these memory management related operations. The compiler takes advantage of the objective-c++ feature to generate code for the C + + object's. Cxx_destruct method, freeing the object. However, for those memory generated through malloc () or objects such as corefoundation, which are not part of the OC object, developers need to release themselves as needed.

In non-arc mode, we can manually control the increment or decrement of the reference count. The following two methods are used:

    • Retain
    • Release

When calling [object retain], reference count +1; when calling [object release], reference count-1. When object is not in use and needs to be freed, call release to make the reference count clear 0 instead of calling Dealloc directly.

In the NSObject protocol, there is Retaincount this method, which is used to query the object's current hold count:

-(Nsuinteger) Retaincount

However, it does not have eggs. However it does not have eggs (important things to say two times). In Arc mode, memory management-related methods are not compiled, and in non-arc, Retaincount often does not reflect the normal retention count of the object. Even when the object has been released, calling to Retaincount again will directly cause crash.

    NSString *str = @ "12456";    NSLog (@ "str retaincount:%lu", (unsigned long) [str retaincount]);    NSNumber *num = @1;    NSLog (@ "num retaincount:%lu", (unsigned long) [num Retaincount]);    NSNumber *numf = @3.1415f;    NSLog (@ "NUMF retaincount:%lu", (unsigned long) [NUMF Retaincount]);

The result of the above code may surprise you:

2015-07-24 14:37:19.238 testmemory[10987:3418823] Str retaincount:42949672952015-07-24 14:37:19.241 TestMemory[ 10987:3418823] num retaincount:182015-07-24 14:37:19.241 testmemory[10987:3418823] NUMF retaincount:1

The retaincount of STR and NUM objects are confusing numbers. The compiler has actually optimized these objects, and this optimization occurs only on certain occasions, so the retaincount of the Numf object is normal. So again, don't try to use Retaincount to do anything.

iOS memory management, that is, for reference counting, call retain and release to tell the system to release memory. Let's raise a chestnut. The following code runs in non-arc mode:

/*! *  Table */@interface table:nsobject@end@implementation table-(void) dealloc{    NSLog (@ "%s", __func__);    [Super Dealloc];} @end/*! *  Guest */@interface Guest:nsobject@property (nonatomic, copy) NSString *name; @property (nonatomic, retain) Table *tabl e;-(Instancetype) Initwithname: (NSString *) name; @end @implementation guest-(instancetype) Initwithname: (NSString *) name{self    = [self init];    if (self) {        self.name = name;    }    return self;} -(void) dealloc{    NSLog (@ "%@ dealloc", self.name);        [Self.name release];    [Self.table release];    [Super Dealloc];} -(void) settable: (table *) table{    [table retain];    [_table release];    _table = table;} @end

 

Two guests to a table to eat the process of reproduction table *table = [[Table alloc] init];        NSLog (@ "table retain count:%lu", (unsigned long) [table Retaincount]);    Guest *guest_1 = [[Guest alloc] initwithname:@ "guest_1"];    NSLog (@ "%@ retain count:%lu", Guest_1.name, (unsigned long) [guest_1 Retaincount]);    guest_1.table = table;        NSLog (@ "table retain count:%lu", (unsigned long) [table Retaincount]);    Guest *guest_2 = [[Guest alloc] initwithname:@ "guest_2"];    NSLog (@ "%@ retain count:%lu", Guest_2.name, (unsigned long) [guest_2 Retaincount]);    guest_2.table = table;        NSLog (@ "table retain count:%lu", (unsigned long) [table Retaincount]);    [Guest_1 release];    NSLog (@ "%@ retain count:%lu", Guest_1.name, (unsigned long) [guest_1 Retaincount]);        NSLog (@ "table retain count:%lu", (unsigned long) [table Retaincount]);    [Guest_2 release];    NSLog (@ "%@ retain count:%lu", Guest_2.name, (unsigned long) [guest_2 Retaincount]); NSLog (@ "table retain count:%lu", (unsigned long) [table Retaincount]);       [Table release]; NSLog (@ "table retain count:%lu", (unsigned long) [table Retaincount]);

above realizes a simple guest to the table to eat the scene: First has prepared a table, came a guest 1, do dinner table, came a guest 2, to dinner table, guests 1 eat good meal leave, guest 2 leave, table use finished, clean table.

First look at two classes, table is very simple, there are no other objects reserved in the class, the Dealloc method calls [Super Dealloc] to guarantee the release of the parent class object. The guest class has two attributes (@property) added, and the modifiers for the properties are copy and retain. iOS automatically creates a get and set method on the property, and such modifiers, such as copy/retain/assign, indicate the way in which the set method has different memory management for attribute values, which is detailed later in this article. As long as you know, copy and retain cause the property value to be preserved in the set method, that is, retaincount+1. The custom Init method is added to the guest class, and note that the method at the beginning of Init must follow the code specification requirements of OC in order to achieve the purpose of calling Init, as in the example initwithname: such a camel-case. The Dealloc method implements the release of the reserved object and finally calls [Super Dealloc]. Settable: The method replicates the property's set method, actually just reproduces the default set method of the retain modifier attribute value in code. As you can see, for a property value of retain, the new value is retained first, the old value is freed, and the new value is assigned to the property, which implements the object's retention. The caller of the set method needs to manage the deallocation of the assigned value.

The above code has the following log:

2015-07-24 10:14:07.623 testmemory[10956:3397055] table retain count:12015-07-24 10:14:07.628 TestMemory[              10956:3397055] guest_1 retain count:12015-07-24 10:14:07.629 testmemory[10956:3397055] table retain Count:2 Table is reserved by the guest object, reference count +12015-07-24 10:14:07.630 testmemory[10956:3397055] guest_2 retain count:12015-07-24 10:14:07.631 testmemory[10956:3397055] Table retain count:3, table is reserved by the guest object, reference count +12015-07-24 10:14:07. 632 testmemory[10956:3397055] guest_1 dealloc-guest_1 reference count is 0, triggering dealloc2015-07-24 10:14:07.632 Te STMEMORY[10956:3397055] guest_1 retain count:12015-07-24 10:14:07.633 testmemory[10956:3397055] table retain count: 22015-07-24 10:14:07.634 testmemory[10956:3397055] guest_2 dealloc-guest_2 reference count is 0, triggering dealloc2015- 07-24 10:14:07.634 testmemory[10956:3397055] guest_2 retain count:12015-07-24 10:14:07.635 TestMemory[10956:3397055] Table Retain count:12015-07-24 10:14:07.636 testmemory[10956:3397055]-[table Dealloc], Table reference count is 0, triggering dealloc2015-07-24 10:14:07.636 testmemory[10956:33970 [] Table retain count:1

As you can see, Retaincount will be +1 after the object is alloc through the Create method. The Table object is Alloc, and is reserved by guest_1 and guest_2 respectively, resulting in a retaincount of 3. When guest calls the release method, the reference count is 0, triggering the Dealloc method of the Guest object, resulting in the Table object reference count-1. The last table calls release, the reference count is 0, and the Table object Dealloc is triggered.

However, as mentioned above, Retaincount does not play a good role in explaining the reference count here. Although the reference count is 0, the last Retaincount is not displayed as 0. This may be the run-time internal processing of the Retaincount method, or the object memory is not immediately released, or the method of invoking the disposed object again after the object dealloc will cause exc_ The crash of bad_access occurs.

2 attribute ownership semantics (ownership semantic)

Cond...

iOS memory management (OBJECTIVE-C)

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.