IOS arc VS mrc learning notes
I,* Core Foundation and objective-c Object Exchange *
The ARC Management mechanism required for Core Foundation and objective-cObject exchange is as follows:
(1) (_ bridge_transfer) op or alternatively CFBridgingRelease (op) is used to consume a retain-count of a CFTypeRef while transferring it over to ARC. This cocould also be represented
id someObj =(__bridge
) op; CFRelease(op);
(2) (_ bridge_retained) op or alternatively CFBridgingRetain (op) is used to hand an NSObject over to CF-land while giving it a + 1 retain count. you shoshould handle a CFTypeRef you create this way the same as you wowould handle a result of CFStringCreateCopy (). this coshould also be represented
CFRetain((__bridge CFType)op); CFTypeRef someTypeRef =(__bridge CFType)op;
(3) _ bridge just casts between pointer-land and Objective-C object-land. If you have no inclination to use the conversions above, use this one.
II,* ARC and IOS4 *
In IOS4, ARC does not have the _ weak keyword, which must be replaced by unsafe_unretained.
III,* Memory leakage in ARC *
Using ARC does not mean that there will be no memory leakage in our project. Under the ARC mechanism, the most common cause of Memory leakage is cyclic strong reference. Common scenarios include:
① Outlet type pointer
The weak attribute should be used to declare pointer variables of the Outlet type.
② Delegate
Make sure to set the delegate attribute to weak. I will not explain the reason. I really don't understand it. Please slam here.
③ Block
The following code is correct in MRC:
MyViewController * __block myController = [[MyViewController alloc] init…]; // ... myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil]; };
However, under the ARC condition, the memory will leak, and the objects pointed to by myController cannot be released.
The reason is that when the variable x declared by the _ block id x is used in the block, the reference count of x is not increased in the MRC condition, but in the ARC condition, the reference count of x is increased by one, please note that !!!!!!!!!!!!
The above problem Code provides the following solutions:
Solution 1:
MyViewController * __block myController = [[MyViewController alloc] init…]; // ... myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil]; myController = nil; };
The simplest solution is to point to nil when myController is used in the block. If no pointer of the strong type points to the object pointed to by myController, the object will be released.
Solution 2:
MyViewController *myController = [[MyViewController alloc] init…]; // ... MyViewController * __weak weakMyViewController = myController; myController.completionHandler = ^(NSInteger result) { [weakMyViewController dismissViewControllerAnimated:YES completion:nil]; };
This scheme uses a temporary _ weak pointer weakMyViewController. Using this pointer in the block will not cause reference count plus one, but there is a hidden risk, when the object is released externally, the operations performed in the block are invalid. Solution 3 below can solve this problem.
Solution 3:
MyViewController *myController = [[MyViewController alloc] init…]; // ... MyViewController * __weak weakMyController = myController; myController.completionHandler = ^(NSInteger result) { MyViewController *strongMyController = weakMyController; if (strongMyController) { // ... [strongMyController dismissViewControllerAnimated:YES completion:nil]; // ... } else { // Probably nothing... } };
That is, a temporary strong type pointer is declared before the myController object is used in the block to point to the weak type pointer. In this case, the strongMyController pointer becomes a valid strong reference, the object to which it points can be guaranteed not to be released.
④ Timer
The timer is also very prone to memory leakage. For example, the following code
@implementation AnimatedView { ?NSTimer *timer; ?} - (id)initWithCoder:(NSCoder *)aDecoder { ? ? if ((self = [super initWithCoder:aDecoder])){ timer = [NSTimer scheduledTimerWithT imeInterval:0.1 target:self selector:@selector(handleTimer:) userInfo:nil repeats:YES]; } return self; } - (void)dealloc { [timer invalidate]; } - (void)handleTimer:(NSTimer*)timer { //do something }
At first glance, there is no problem with this code, but it is found that the dealloc method will not be called after running, self has a strong reference of timer, and timer has a strong reference of self, typical cyclic reference!
The solution is to set the timer attribute to _ weak.
IV,* @ Autoreleasepool and NSAID utoreleasepool *
ARC does not support the use of NSAID utoreleasepool, but can be replaced by @ autoreleasepool. @ Autoreleasepool can be used in both the ARC environment and non-ARC environment, and the efficiency is higher than the former, which is described on the official website of Apple as follows:
ARC provides @autoreleasepool blocks instead. These have an advantage of being more efficient than NSAutoreleasePool.
V,* Use the new rules required by ARC *
① Do not call [super dealloc] In the dealloc method;
② Retain/release/retainCount/autorelease cannot be used
③ NSAllocateObject/NSDeallocateObject cannot be used
④ NSZone cannot be used
⑤ The Objective-C object cannot be a member of the C language struct (struct/union ).
Reference link:
This is not a technical issue with arc & mrc.
Objective-c memory management MRC and ARC
Experiences in using ARC (2)
Performance Comparison: cocos2d-iphone v2 vs v3 vs Sparrow and ARC vs MRC
IPhone development (4)-cycle of ARC reference Transitioning to ARC Release Notes