“Objective-C advanced programming” dry Trilogy (1): reference count

After summing up the Effective Objective-C, but also want to read an advanced iOS book, did not hesitate to select the Objective-C advanced programming:


Objective-C Advanced Programming: iOS and OS X multithreading and memory management

There are three chapters in this book. I summarize each chapter and add the appropriate extensions to share it. We can look at the overall structure of these three articles from the following graph:


“Objective-C advanced programming” dry Trilogy

Note that this structure is not consistent with the structure of the book, but the book’s structure as a reference, a slight adjustment.

This is the first article: reference count, a simple sentence:
Objective-C through the mechanism of the retainCount to determine whether the object needs to be released. After each iteration of the runloop, the retainCount of the object is checked, and if retainCount is equal to 0, it means that the object has no place to continue to use and can be released. Whether it is a manual management of memory, or ARC mechanism, are through the retainCount to carry out memory management.

Take a look at manual memory management:

Manual memory management

I personally think that before learning a new technology, you need to understand its core ideas. After understanding the core ideas, grasp the technical point will be faster:

Memory management thought

  • Thought one: the object of their own generation, their holdings.
  • Thought two: not the object of their own generation, they can hold.
  • Thought three: no longer need to hold their own objects when the release of objects.
  • Thought four: the object of their own can not be released.

From the above point of view, the operation of the object can be divided into three types: generation, possession, release, plus waste, a total of four. They correspond to changes in the Objective-C method and reference count:

Object manipulation Objecctive-C method Citation count change
Generate and hold objects Alloc/new/copy/mutableCopy et al +1
Hold object Retain method +1
Release object Release method -1
Abandoned object Dealloc method nothing

The picture in the book to intuitively feel these four operations:


images from: Objective-C Advanced Programming: iOS and OS X multithreading and memory management

Here are four ideas to explain one by one:

Thought one: the object of their own generation, their holdings

When an object is generated, the object is held when the object is created by the method with the following name:

  • Alloc
  • New
  • Copy
  • MutableCopy

For:

ID obj = [[NSObject alloc] init]; / / object to hold the new generation

After this line of code, point to generate and hold [[NSObject alloc] init] pointer is assigned to the obj, that is to say that the obj pointer strong reference [[NSObject alloc] init] this object.

The same applies to the new method:

ID obj = [NSObject new]; / / object to hold the new generation

Note: This is the case that the
pointer to the pointer to the object is not limited to the names of the four methods above, as well as all the method names that start with them:

  • AllocThisObject
  • NewThatObject
  • CopyThisObject
  • MutableCopyThatObject

For:

ID obj1 = [obj0 allocObject]; / / the naming rules, to generate and hold objects

Its internal implementation:

- (ID) allocObject obj alloc] init] {id = [[NSObject; / / holds a new generation of object return obj;}

Conversely, if they do not conform to the naming rules, then it does not hold the resulting object, internal createObject method returns a
object does not comply with the naming rules of implementation:

- (ID) createObject obj alloc] init] {id = [[NSObject; / / holds a new generation of object [obj autorelease]; / / get the object, but they do not hold return obj;}

After this method returns, the returned object cannot be held. Because autorelease is used here. Autorelease provides the ability to automatically and correctly release an object when it is out of the specified range of survival (details will be presented later).


images from: Objective-C Advanced Programming: iOS and OS X multithreading and memory management

In other words, the formation of a caller does not hold the object can be achieved by autorelease (for example, the array NSMutableArray method). My personal understanding is that the ownership of the object is transferred to the auto release pool by the autorelease method. Thus, the caller gets the object, but the object is not held by the caller.

This is not the case with the naming convention to draw the idea two:

Thought two: not the object of their own generation, they can hold

We now know that it is impossible to hold an object only by the method that returns an instance of the object that does not conform to the naming convention. However, we can hold the returned object by an operation. This method is to allow the pointer variable to hold the newly generated object by the retain method:

ID obj = [NSMutableArray array]; / generate their own and hold the object [obj retain]; / / object to hold the new generation

Note that the [NSMutableArray array] is not the object of its own to be held by the above described by the autorelease method. So if you want to hold this object, you need to implement the retain method.

Thought three: no longer need to hold their own objects when the release of objects

The owner of the object is obligated to release the object when it is no longer needed. Note that there is an obligation, not a right, to pay attention to the difference between the two words.

Take a look at the example of releasing objects:

ID obj = [[NSObject alloc] init]; / / holds a new generation of object [obj doSomething]; / / use the object to do some things [obj release]; / / done, release the object

Also applies to objects that are not created and held by themselves (Ref. two):

ID obj = [NSMutableArray array]; / generate their own and hold the object [obj retain]; / / holds a new generation of object [obj soSomething]; / / use the object to do some things [obj release]; / / done, release the object

Possible interview question: does the release method that calls the object destroy the object? The answer is:
will call the release method on the object is the object reference counter -1, when the object’s reference count to 0 when the dealloc method to call the object will release the memory object.

Thought four: unable to release the object of their own holdings

In the release of the object, we can only release the object has been held, the object is not their own can not be released. This is very common sense: it’s like you can withdraw money from your own bank card, it is not right to take someone else’s money… Just give me an example.

Two kinds of situations that are not allowed:

1 release an abandoned object

ID obj = [[NSObject alloc] init]; / / holds a new generation of object [obj doSomething]; / / [obj / / release] using the object; release the object no longer holds [obj release]; / / object release has been abandoned, collapse

2 release the object that you do not hold

ID obj = [NSMutableArray array]; / generate their own and hold the object [obj release]; / / release of their holdings of non object

Thinking: what are the circumstances that cause the object to lose ownership?

  1. Pointer variable pointing to an object to another object.
  2. Set the pointer variable pointing to an object to nil.
  3. When the program releases an owner of the object.
  4. When objects are removed from the collection class.

Now that we know the four ideas of reference counting memory management, let’s take a look at the method of counting the four operations:

Implementation of alloc/retain/release/dealloc

In a sense, the implementation of GNUstep and Foundation framework is similar. So the author of this book through the GNUstep source code to speculate the realization of apple Cocoa framework.

The following is the beginning of each method, while using GNUstep and Apple’s implementation (tracking the implementation of the program and the author’s guess) to compare their implementation.

GNUstep implementation:

Alloc method

//GNUstep/modules/core/base/Source/NSObject.m + alloc: (ID) alloc [self allocWithZone: (NSDefaultMallocZone) {return} +]; (ID) allocWithZone: (NSZone* z) {return NSAllocateObject (self, 0, z);}

Here the NSAllocateObject method assigns an object and looks at its internal implementation:

//GNUstep/modules/core/base/Source/NSObject.m NSAllocateObject: struct obj_layout {NSUInteger retained;}; NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone) {int size = calculation for objects required memory size; ID new = NSZoneMalloc (zone, 1, size); / / returns a new instance of memset (new, 0; new, size) = (ID) ((obj) & new [1];})

NSAllocateObject function through the NSZoneMalloc function to allocate the memory space required to store the object. Obj_layout is used to save the reference count and write it to the object’s memory header.

The reference count of an object can be obtained by the retainCount method:

GNUstep/modules/core/base/Source/NSObject.m retainCount: - (NSUInteger) retainCount return NSExtraRefCount (self) {} + 1; inline NSUInteger NSExtraRefCount (ID anObject) {return ((obj_layout) anObject [-1].retained);}

As we can see, after entering anObject to NSExtraRefCount, the reference count is obtained by accessing the.Retained variable in the head of the object.

Retain method

//GNUstep/modules/core/base/Source/NSObject.m retain: (ID retain) {NSIncrementExtraRefCount (self); return self;} inline void NSIncrementExtraRefCount (ID anObject) {//retained variable exceeds the maximum value, an exception is thrown (if ((obj) anObject) [-1].retained = UINT_MAX - 1) {[NSException raise: NSInternalInconsistencyException format: NSIncrementExtraRefCount (asked) @ to increment too far "]}; ((obj_layout) anObject) [-1].retained++; //retained variable +1}

Release method

//GNUstep/modules/core/base/Source/NSObject.m release (void release) {/ / if the reference count = 0, call the dealloc function if (NSDecrementExtraRefCountWasZero (self) {[self dealloc]}}); BOOL NSDecrementExtraRefCountWasZero (ID anObject) {/ / if the current value of retained = 0 or Yes (if ((obj) anObject) [-1].retained = = 0) {return YES;} / / if greater than 0 -1, and returns NO ((obj) anObject) [-1].retained--; return NO;}

Dealloc method

//GNUstep/modules/core/base/Source/NSObject.m dealloc - (void) dealloc (self) {NSDeallocateObject}; inline void NSDeallocateObject (ID anObject) {obj_layout o = & ((obj_layout) anObject) [-1]; free (o); / / release}

Summarize some of the above methods:

  • The integer value of the reference count is stored in the Objective-C object.
  • After calling the alloc or retain method, the reference count +1.
  • After calling release, the reference count -1.
  • When the reference count is 0, call the dealloc method to discard the object.

Look at Apple’s implementation:

Apple’s implementation

Alloc method

By setting a breakpoint on the alloc class method of the NSObject class, we can see the function that is executed by the:

  • +alloc
  • +allocWithZone:
  • Class_createInstance// generation instance
  • Calloc// allocated memory block

RetainCount:

  • __CFdoExternRefOperation
  • CFBasicHashGetCountOfKey

Retain method

  • __CFdoExternRefOperation
  • CFBasicHashAddValue

Release method

  • __CFdoExternRefOperation
  • CFBasicHashRemoveValue

We can see that they all call a common __CFdoExternRefOperation method.

Take a look at it:

Int __CFDoExternRefOperation (uintptr_t OP, ID obj) {CFBasicHashRef table = hashtable object (obj); int count; switch (OP) {case OPERATION_retainCount: count = CFBasicHashGetCountOfKey (table, obj); return count; break case; OPERATION_retain: count = CFBasicHashAddValue (table, obj); return obj; case OPERATION_release: = count CFBasicHashRemoveValue (table, obj); return count = = 0;}}

It can be seen that the __CFDoExternRefOperation through the switch statement according to the different operation to invoke specific methods, if OP is OPERATION_retain, you remove the method for the realization of retain and so on.

You can guess the upper retainCount, retain, release method:

- (NSUInteger retainCount) {return (NSUInteger) ____CFDoExternRefOperation (OPERATION_retainCount, self);} - {return (ID) retain (ID) ____CFDoExternRefOperation (OPERATION_retain, self);} / / where the return value should be ID, the original book here should be wrong - (ID release) {return (ID) ____CFDoExternRefOperation (OPERATION_release, self);}

We look at each statement in the switch implementation of the function name, it seems that the hash table (Hash), which means that Apple’s reference count management should be implemented through the hash table.


images from: Objective-C Advanced Programming: iOS and OS X multithreading and memory management

In this case, key is a memory block address, and the corresponding value is a reference count. That is to say, it preserves the information: the number of references to some of the referenced memory blocks.

So what are the benefits of using a hash table to manage memory?

Because the counter holds the address of the memory block, we can use the table to:

  • Confirm the location of the damaged memory block.
  • In the detection of memory leaks, you can see the existence of the object of the holder.

Autorelease

Autorelease introduction

When an object is out of scope, the release method of the object instance is called, and the specific use of the autorelease is as follows:

  1. Generate and hold NSAutoreleasePool objects.
  2. Calling the autorelease method of the assigned object.
  3. Abandoned NSAutoreleasePool object.

images from: Objective-C Advanced Programming: iOS and OS X multithreading and memory management

All objects that call the autorelease method will call the release method (reference count -1) when the NSAutoreleasePool object is discarded:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ID obj = [[NSObject alloc] init]; [obj autorelease]; [pool drain]; / / obj is equivalent to calling the release method

NSRunLoop in each cycle, the NSAutoreleasePool object will be generated or abandoned.
, that is to say, if there are a large number of autorelease variables, before the NSAutoreleasePool object (abandoned once the listener to RunLoop is about to enter the sleep wait state, the release of NSAutoreleasePool), will not be destroyed, easily lead to the problem of the proliferation of memory:

For (int i = 0; I < imageArray.count; i++) {*image = imageArray[i]; [image doSomething];}

images from: Objective-C Advanced Programming: iOS and OS X multithreading and memory management

Therefore, it is necessary for us to nest an auto release pool at the appropriate time to manage the autorelease variable:

For (int i = 0; I < imageArray.count; i++) {/ / *pool = [[NSAutoreleasePool alloc] NSAutoreleasePool temporary pool init] UIImage; *image = imageArray[i]; [image doSomething]; [pool drain];}

images from: Objective-C Advanced Programming: iOS and OS X multithreading and memory management

May be out of the interview question: when will create an automatic release pool?
answer: run the loop to detect the event and start, you will create an automatic release pool, and Zi Xiancheng’s runloop default is not working, can not be created automatically, you must manually create.
for: main
custom NSOperation class in the pool must be added. Otherwise, when the scope is out, the automatically released object will cause memory leaks because it does not have an auto release pool.

Autorelease implementation

As in the above, we still look at the realization of GNUstep and apple.

GNUstep implementation

//GNUstep/modules/core/base/Source/NSObject.m autorelease - (ID) autorelease {[NSAutoreleasePool addObject:self]}

If you call the autorelease method of the NSObject class, the object is appended to an array of NSAutoreleasePool objects that are in use (the author assumes a simplified source code):

//GNUstep/modules/core/base/Source/NSAutoreleasePool.m + addObject (void) addObject: (ID) anObj *pool = {NSAutoreleasePool NSAutoreleasePool object if is used (pool! = Nil) {[pool addObject:anObj];}else{NSLog (@ NSAutoreleasePool object does not exist ");}} - (void) addObject: (ID) anObj {[pool.array addObject:anObj];}

In other words, the essence of the autorelease instance method is to call the addObject method of the NSAutoreleasePool object, which is then appended to an array of NSAutoreleasePool objects that are in use.

Look at the NSAutoreleasePool drain method:

- (void) drain {[self dealloc];} (void) dealloc {[self emptyPool];} (void) emptyPool {for (ID obj in array) {[obj release]}}

We can see that in the emptyPool method, it is true that every object in the array is release.

Apple’s implementation

We can confirm the realization of apple autorelease through objc4/NSObject.mm:

Objc4/NSObject.mm AutoreleasePoolPage class AutoreleasePoolPage static inline void (*push) {{/ / generate or hold the object of class NSAutoreleasePool static inline void pop} (void *token) {/ / NSAutoreleasePool (releaseAll) abandoned objects; inline ID autorelease} static (ID obj) {/ / addObject method is equivalent to the class NSAutoreleasePool AutoreleasePoolPage *page = being used an instance of AutoreleasePoolPage; autoreleaesPoolPage-> add (obj)} ID *add (ID obj) {/ / object is appended to the internal array void (releaseAll) {} / / call the internal array object release}}; / / void *objc_autoreleasePoolPush stack (VO ID) {if (UseGC) return nil; return AutoreleasePoolPage: (push): void objc_autoreleasePoolPop;} / / stack (void *ctxt) {if (UseGC) return; AutoreleasePoolPage:: Pop (ctxt);}

Look at the external call:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; / / ID obj is equivalent to objc_autoreleasePoolPush = [[NSObject alloc] init]; [obj autorelease]; / / is equivalent to objc_autorelease (obj) [NSAutoreleasePool showPools]; / / [pool drain] view NSAutoreleasePool status; / / is equivalent to objc_autoreleasePoolPop (pool)

Look at the function name can know on autorelease. The implementation of push, pop operation. Release operation is performed when an object is destroyed.

Possible interview questions: apple is how to achieve autoreleasepool?
autoreleasepool to achieve a queue array form, mainly through the following three functions.
– objc_autoreleasepoolPush
– objc_autoreleasepoolPop (press) (POP)
– objc_autorelease (internal release)

ARC memory management

Memory management thought

The above study of the non ARC mechanism under the manual management of memory, for the reference count of the operation and automatic release of the relevant content pool. Now learn about the knowledge of the ARC mechanism.

ARC and non ARC memory management mechanism under the same:

  • The object of their own generation, their holdings.
  • Not their own generation of objects, they can hold.
  • Object is no longer needed when you hold the object.
  • Objects that are not held by themselves cannot be released.

In the ARC mechanism, the compiler can automatically carry out memory management, reducing the workload of development. But we still need four kinds of ownership modifiers to manage the memory with ARC

Four ownership modifiers

However, in the case of the ARC mechanism, we sometimes need to add a statement of ownership (the following is taken from the official document):

  • __strong:is the default. object remains as long there a strong pointer alive to it. is as An
  • __weak:specifies a reference does keep the object A weak reference is set nil when to there are no strong references alive. to the referenced not object. that
  • __unsafe_unretained:specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object it references is deallocated, the pointer is left dangling.
  • __autoreleasing:is used to arguments are by reference (ID *) and autoreleased are on return. denote that passed

Here are a few of these modifiers:

__strong modifier

The __strong modifier is the default ownership modifier for the ID type and object type:

__strong usage:

ID obj = [NSObject alloc] init];

Equivalent to:

ID __strong obj = [NSObject alloc] init];

Look at the process of memory management:

{ID __strong obj = alloc] init]; //obj holds object} //obj beyond its scope, strong reference failure [NSObject

The __strong modifier represents a strong reference to the object. A strong reference variable is discarded when it is out of scope.

In the case of __strong modifiers that are assigned to each other:

ID __strong obj0 = [[NSObject alloc] init]; //obj0 A ID __strong obj1 held object = [[NSObject alloc] init]; //obj1 B ID __strong obj2 held object = nil; //ojb2 = obj1 obj0 does not hold any object; //obj0 strong reference object B object; A is no longer ojb0 references, abandoned obj2 = obj0; //obj2 strong reference object B (now obj0, ojb1, obj2 have strong reference object B) obj1 = nil; //obj1 B obj0 = no longer strong reference object nil; //obj0 is no longer a strong reference object B obj2 = nil; //obj2 is no longer a strong reference object B, there is no longer any reference to the strong references like B, B abandoned object

Moreover, strong can make a variable initialized to nil:id strong obj0;
also applies to: ID weak obj1; ID autoreleasing obj2;

Make a summary: after __strong modification, the equivalent of a strong reference to an object. Once the object has a strong reference to itself, the reference count will be +1, the system will not be abandoned. And if the object is no longer a strong reference, it will be abandoned.

__strong internal implementation:

Generate and hold objects:

{ID __strong obj = alloc] init]; //obj hold object} ([NSObject)

Compiler simulation code:

ID obj = objc_mesgSend (NSObject, @selector (alloc); objc_msgSend (obj), @selector (init)); objc_release (obj); / / beyond the scope of the object

Take a look at the use of naming rules other than the construction method:

{ID __strong obj = array];}; [NSMutableArray

Compiler simulation code:

ID obj = objc_msgSend (NSMutableArray, @selector (array)); objc_retainAutoreleasedReturnValue (obj); objc_release (obj);

The role of objc_retainAutoreleasedReturnValue: hold the object, register the object to autoreleasepool and return.

There are also objc_autoreleaseReturnValue, look at its use:

(ID) array {[[NSMutableArray alloc] init]};}

Compiler simulation code:

(ID) array {obj = objc_msgSend (NSMutableArray, @selector (alloc)); objc_msgSend (obj, init (@selector)); return objc_autoreleaseReturnValue (obj);}

Objc_autoreleaseReturnValue: returns the object registered to autoreleasepool.

__weak modifier

__weak usage:

The __weak modifier mostly solves the circular reference problem: if two objects are strong references to each other, and lost all external references to himself, it will form a “isolated island”, the island will never be released for:

@interface Test:NSObject __strong {ID obj_;} - (void) setObject: (ID __strong obj); @end @implementation Test (ID) - init {self = [super init]; return self;} - (void) setObject: (ID __strong obj) {obj_ = obj;} @end
{ID Test0 = [[Test alloc] init]; //test0 ID test1 = strong reference object A [[Test alloc] init]; //test1 B [test0 setObject:test1] strong reference object; //test0 [test1 setObject:test0] //test1 B reference object; strong reference object A}

Because the generated object (first, second row) and the set method (line third, line fourth) are strong references, it will cause the two objects to each other strong reference to each other:


Objective-C Advanced Programming: iOS and OS X multithreading and memory management

So we need to break one of those strong references:

@interface Test:NSObject {ID __weak obj_; / / by __strong into __weak} - (void) setObject: (ID __strong obj); @end

In this way, the two is only a weak reference to each other:


Objective-C Advanced Programming: iOS and OS X multithreading and memory management

__weak internal implementation

{ID __weak obj1 = obj;}

Compiler simulation code:

ID obj1; objc_initWeak (& obj1, obj); / / initialize with a __weak variable ID TMP = objc_loadWeakRetained (& obj1); / / remove the object with the __weak modifier variable referenced and retain objc_autorelease (TMP); / / object registration to autoreleasepool objc_destroyWeak (& obj1); / / release with __weak variable

This confirms one of the features of weak: using a variable with the weak modifier, that is, using the object registered in autoreleasepool.

Here need to focus on the objc_initWeak method and objc_destroyWeak method:

  • Objc_initWeak: initialization with __weak variables, specifically through the implementation of objc_strongWeak (&amp, obj1, obj) method, the obj object to & obj1 as key into a weak table (Hash).
  • Objc_destroyWeak: release variables with __weak. Specific through the implementation of objc_storeWeak (& obj1,0) method, in the weak table query & obj1 this key, this key will be removed from the weak table.

Note: because the same object can be assigned to a number of variables with __weak, so for the same key, you can register the address of multiple variables.

When an object is no longer held by anyone, it needs to be released:

  • Objc_dealloc
  • Dealloc
  • _objc_rootDealloc
  • Objc_dispose
  • Objc_destructInstance
  • Objc_clear_deallocating gets the discarded objects from the weak table address will contain all the __weak modifier with variable address assignment in the record for the nil from the weak table to delete the record from the reference count in the table delete discarded objects.

__autoreleasing modifier

__autoreleasing usage

ARC, @autoreleasepool can be used to replace the NSAutoreleasePool class object, using the __autoreleasing modifier variable to replace the autorelease method calls ARC (invalid object is registered to the autoreleasepool).


Objective-C Advanced Programming: iOS and OS X multithreading and memory management

When it comes to autoreleasing modifiers, you have to mention weak:

ID __weak obj1 = obj0; NSLog (class = @% @ ", [obj1 class]);

Equivalent to:

ID __weak obj1 ID __autoreleasing = obj0; TMP = obj1; NSLog (class = @% @ ", [tmp class]); / / the actual access is registered to the object automatically release pool

Note two the equivalent code, object NSLog statement inside access is not the same, it shows: in the __weak variable access modifiers (obj1) access must be registered to the autoreleasepool object (TMP). Why?

Because the __weak modifier holds only a weak reference to the object, that is to say, when the object is accessed in the future, there is no guarantee that it has not been discarded. So if you register this object in autoreleasepool, you can ensure that the object exists before the end of the @autoreleasepool block.

__autoreleasing internal implementation

Assignment of an object to a autorelease method with the __autoreleasing modifier equivalent to the ARC method when the object is invalid.

@autoreleasepool{ID obj = [[NSObject alloc] init];}

Compiler simulation code:

ID pool = objc_autoreleasePoolPush (//pool); ID obj = objc_msgSend stack (NSObject, @selector (alloc); objc_msgSend (obj), @selector (init)); objc_autorelease (obj); objc_autoreleasePoolPop (pool) //pool stack;

Here we can see the pool into the stack, the implementation of autorelease, out of the stack of the three methods.

ARC rules

We know that the compiler will help us manage memory in the ARC mechanism, but we still have to follow some rules during the compile time:

  1. Cannot use retain/release/retainCount/autorelease
  2. Cannot use NSAllocateObject/NSDeallocateObject
  3. Method name rules for memory management must be observed
  4. Don’t explicitly call dealloc
  5. Use @autorelease block instead of NSAutoreleasePool
  6. Cannot use area (NSZone)
  7. Object type cannot be used as a member of the C language structure
  8. Explicit conversion of ID and void*

1 can not use retain/release/retainCount/autorelease

Using the retain/release/retainCount/autorelease method under the ARC mechanism can cause the compiler to report errors.

2 can not use NSAllocateObject/NSDeallocateObject

Using the NSAllocateObject/NSDeallocateObject method under the ARC mechanism can cause the compiler to report errors.

3 must adhere to the memory management method name rules

The method of generating or holding objects must follow the following naming conventions:

  • Alloc
  • New
  • Copy
  • MutableCopy
  • Init

The first four methods have been introduced. The requirements on the init method is more stringent:

  • Must be instance method
  • Object must be returned
  • The type of the returned object must be the object type of the ID type or method declaration class

4 do not explicitly call dealloc

When the object is abandoned, the system calls the dealloc method of the ARC, whether or not it is valid.

We can only write some actions that need to be done in the dealloc method, such as removing the registered observer object, but not the dealloc method.

Note that when the ARC is not valid, you need to call [super dealloc]:

- (void dealloc) {/ / the object [super dealloc];}

5 use @autorelease block instead of NSAutoreleasePool

ARC must use the @autorelease block instead of NSAutoreleasePool.

6 cannot use area (NSZone)

NSZone has been ignored in the current runtime system (the OBC2 setting environment).

7 object variables cannot be used as members of the C language structure

If there is a Objective-C object variable in the C language structure, it will cause an error, because the C language has no method to manage the life cycle of the member of the structure.

8 explicit conversion of ID and void*

Under ARC, these two types can be assigned directly

ID obj = [NSObject init]; void *p = obj; id = alloc] o = p;

But in the ARC will cause compile error. To avoid errors, we need to convert by __bridege.

ID obj = [[NSObject alloc] init]; void *p (__bridge void*) = obj; id = O / explicit conversion (__bridge ID P); / / explicit conversion

attribute

Look at the relationship between the property declaration and the ownership qualifier

Property key Ownership modifiers
Assign __unsafe_unretained
Copy __strong
Retain __strong
Strong __strong
__unsafe_unretained __unsafe_unretained
Weak __weak

Let’s say that the unsafe_unretained:unsafe_unretained means that the access method is directly assigned to the instance variable.

Here “unsafe” is relative to weak. We know that when the weak object is destroyed, the pointer is automatically set to nil. And __unsafe_unretained will not, but become empty pointer. It should be noted that there is no problem of null pointers when dealing with non object attributes.

The first chapter introduces the second finished, will be released on Monday.

Extended literature:

  1. Apple:Transitioning to ARC Release Notes
  2. Mosquito repellent sauce: probably the most comprehensive memory management article in history
  3. Feifei: smile and may encounter iOS written questions (6) — memory management
  4. “IOS programming (Fourth Edition)”

This article has been synchronized to the personal blog: Portal

This article has been printed on the copyright, for reprint please visit the copyright print. Forty-eight million four hundred and twenty-two thousand nine hundred and twenty-eight

Obtain authorization