iOS tamping: Memory managementarticle turn from memory management
The most recent learning plan is to re-hone the mechanism of iOS and learn to summarize and add to your own thinking.
If there is an incorrect place, correct me.
Directory:
- Basic information
- Old-fashioned details
- New era
The basic information objective-c provides two ways of managing memory.
MRR (manual retain-release) manual memory management
This is based on the reference counting implementation, which is implemented by NSObject and runtime environment work together.
ARC (Automatic Reference counting) auto-referencing technology
ARC uses the same reference counting mechanism based on MBR, except that the system helps us to insert the appropriate memory management method when compiling.
Good practices can effectively avoid memory-related problems
Based on memory, there are two main types of errors
- Empty or overwrite memory that is still in use
This emptying usually causes the app to crash and even user data is overwritten
- Not emptying memory that is not already needed can cause memory leaks
Can cause system performance to degrade and applications to be terminated by the system
In fact, we should not only manage memory from the perspective of reference counting, which will let us dwell on the underlying details. We should be standing in the angle of object ownership and object graphs to manage memory
You can use a picture like this to illustrate:
The details of the old times one. Basic memory management guidelines basic memory Management Guidelines: Cocoa provides us with these guidelines
You own any object you create
We create an object by naming the prefix "Alloc", "new", "Copy", or "mutablecopy" method
You can take ownership of an object using retain
With retain to get ownership of objects, there are two main scenarios for using retain
- In accessor method or Init method. To get ownership of the objects you want to store
- In some scenarios it is possible to prevent an object from being removed and we can retain it
When you are no longer need it, you must relinquish ownership of a object you own
When we need to release an object ownership, we send a release or Autorelaese message to it.
You must not relinquish ownership of a object you does not own
Do not release ownership of objects that you do not own
About Dealloc:
NSObject provides us with a dealloc method that will be called automatically when the object is destroyed. The main purpose of this method is to empty the object's own memory and the resources it holds. For example:
NSObject@property (nsstring *firstname; @property (nsstring *lastname; @property (nsstring *fullname; @end
@implementation Person- (void)dealloc [_firstName release]; [_lastName release]; [super dealloc];}@end
It should be emphasized that: never call the Dealloc method yourself
At the end of the dealloc, you need to call Super class Dealloc
Two. In-Practice memory management Guidelines 1. Use the access method to simplify memory management.
如果代码中都是一堆retain release,必然不是一个好的情况。在存取方法里面进行retain和release的操作能够简化内存管理。例如:
-(void) SetCount: (nsnumber *) newcount { retain]; release]; //Make the new assignment. _count = Newcount;}
2. Use the accessor method to set the property value
Compare the following code, the first one using the access method to set, the second directly to the instance variable operation. Obviously we should adopt the first, using the second case, the simple situation is OK, if the situation is complicated, it is very error-prone. and operates directly on instance variables, and does not raise KVO notifications.
-(void) Reset { nsnumber *zero = [[Initwithinteger:0]; [release];} -(nsnumber *zero = [[initwithinteger:release]; _count = zero;}
3. Do not use accessor in initialization methods and Dealloc methods Methods
Apple says in the Advanced Memory Management Programming Guide:
Don ' t use Accessor Methods in Initializer Methods and dealloc The only places you shouldn ' t use Accessor Methods to set an Instance variable is in initializer methods and dealloc. To initialize a counter object with a number object representing zero, you might implement an Init method as follows:
- init { self = [super init]; if (self) { _count = [[NSNumber alloc] initWithInteger:0]; } return self;}
The only place where you don't need to use accessor methods is initializer and dealloc. There is no explanation in Apple's official document why. After a review, the main reason is that the state of the object is uncertain, has not been fully initialized, and caused some problems.
For example, this class or subclass overrides the Setmethod, which calls some other data or methods that require a fully initialized object. In Init, the state of the object is indeterminate.
For example, a subclass overrides the set method and carries out some subclass-specific operations, which can cause the problem to be sent if the parent class uses accessor Methods directly in Init.
Other problems are, like triggering KVO notification, and so on. [^1] [^2]
In short, remember that this principle is the most important to remember in development.
In the development, I found that some people are inadvertently or do not know the direct use of Self.property = XXX in the Init method to assign values, leaving some hidden trouble. Swift removes the way to deal directly with instance variable. The unified use of property for management, and init
strict rules, improve security, solve the human factors caused by errors. Students interested in Swift are welcome to continue reading. From Objective-c to Swift
[^1]: StackOverflow [^2]: Objc-zen-book
4. Use weak references to avoid reference loops
We all know that in arc, weak references are implemented by declaring the property's attribute as weak.
In MRR, it is by referencing the object, but not retain it (a weak reference is a non-owning relationship where the source object does not retain the obj ECT to which it have a reference)
In cocoa, it is typical to have delegate,data source with weak references, notification observer
We need to pay attention to handling weak reference objects, and if you send information to objects that have already been destroyed, it will cause crash. The object that is normally weakly referenced is responsible for notifying other objects when it is destroyed.
Like Notification Center holds a weak reference to observer, so when the weak reference observer prepares to end the life cycle, observer needs to notify notification Center,unregister itself.
4. Do not let the object you are using be removed
Observe the following two kinds of code, the first because there is no retain, the object may be removed, and the second is the correct way of writing
REMOVEOBJECTATINDEX:N]; removeobjectatindex:n]; Release];
5. The collections class has ownership of the objects it collects
such as Nsarray,dictionary and so on. They are responsible for the ownership of the objects they collect, so we do not need to retain the objects to be stored in. For example, the following allocednumber do not need to retain.
10; i++) { nsnumber *allocednumber = [[release];}
6. Finally, the above ownership policy is based on the retain count implementation
- When you create an object, its retain count is 1.
- When you send retain information to an object, it's retain count +1
- When you send release information to an object, his retain count-1
When you send autorelease information to an object, at the end of the current Autorelease pool block, retain count-1
- When the retain count of an object drops to 0, it is dealloced.
Three. Using Autorelease Pool block
Autorelease Pool provides us with a mechanism to avoid objects being destroyed immediately when we dismiss an object's ownership (for example, returning an object from a method)
A autorelease pool Block object is this:
@autoreleasepool { //Code that creates autoreleased objects.}
At the end of the block, all the objects that received the Autorelease message will receive the release message.
In the new era of arc, the Autorelease pool block is primarily designed to handle the avoidance of memory spikes, but we don't need to manually add the Autorelease code anymore.
For example, the following example (a little hard-made, mainly to clarify)
If we do not add autoreleasepool, we will finally need to release 10000*10000 objects, instead of releasing 10,000 objects each time each loop
-(void) usealoadofnumbers {for (10000; ++j) { @autoreleasepool { NSNumber *number = [NSLog (%p", number);}}}
New era
Read more: iOS tamping: Memory management in the arc era
iOS tamping: Memory management