This article focuses on how to switch between MRC and ARC freely in development. Although MRC projects rarely exist, but understand its essence, namely ARC.

One point to note in this article is that the part involving autorelease will be uniformly covered in memory management (vi) Autorelease.

A, MRC

1.1 methods

MRC memory management, in the call related memory methods as follows:

1.2 Memory Management Principles

So how do you call these methods? The memory management rules are as follows:

  • Self generated objects, own
- (void)rule1
{
    /* * generate and hold the object */
    id obj0 = [[NSObject alloc] init];
    id obj1 = [NSObject new];
}
Copy the code
  • Objects that are not generated by themselves can be held by themselves
- (void)rule2
{
    /* * Hold non-generated objects */
    id obj = [NSArray array]; // An object that is not generated by itself and exists but is not owned by itself
    [obj retain]; // Own the object
}
Copy the code
  • Release when you no longer need to hold objects yourself
- (void)rule3
{
    /* * Releases */ when you don't need an object you own
    id obj = [[NSObject alloc] init]; // Hold the object at this time
    [obj release]; // Release the object
    /* * The pointer to the object is still kept in the obj variable * but the object has been freed and cannot be accessed */
}
Copy the code
  • Objects that are not owned by you cannot be released
- (void)rule4
{
    /* * Objects that you do not own cannot be released */
    id obj = [NSArray array]; // An object that is not generated by itself and exists but is not owned by itself
    // The compiler will run crash or error
    // Under MRC, calling this method causes the compiler to report issues. The behavior of this operation is undefined and may cause runtime crash or other unknown behavior
    [obj release];
}
Copy the code
Where the object is not generated by itself, and the object exists, but does not own this feature is implemented using autoRelease, the example code is as follows:Copy the code
 - (id) getAObjNotRetain {
    id obj = [[NSObject alloc] init]; // Own the object
    [obj autorelease]; // The obtained object exists, but you do not own it
    return obj;
 }
Copy the code

Autorelease makes it possible for objects to be released correctly after they have expired (by calling the Release method). When release is called, the object is released immediately. When AutoRelease is called, the object is not released immediately. Instead, the object is registered in autoReleasepool.

This section will be detailed in memory management (vi) autorelease.

1.3 a setter method

Now that we know how to call methods, we still need to know something about @property, although Xcode will automatically generate setters for us under MRC as well. Now let's see how they are implemented.Copy the code

1.3.1 Attributes of memory management semantics

Under MRC, there are the following:

1.3.2 implementation

Start with an example class, see -mrc – reference Counting for example code

@interface BFPerson : NSObject

@property (nonatomic, assign) NSInteger age;

@property (nonatomic, copy) NSString *name;

@property (nonatomic, retain) BFBook *book;

@property (nonatomic, unsafe_unretained) BFPen *pen;

@end
Copy the code
  • assign

For scalar types, assign is used, and since no reference counting is involved, its setters are simple assignment operations.

- (void)setAge:(NSInteger)age
{
    _age = age;
}

-(NSInteger)age
{
    return _age;
}
Copy the code
  • retain

For the object type, the reference count of the object needs to be managed. The meaning of retain must indicate ownership, i.e. strong reference. In this case, you need to retain the passed object and increase the reference count to indicate that a new pointer strongly referenced it.

As for why release is required prior to retain, take a look at the sample code.

- (void)setBook:(BFBook *)book { if (_book ! = book) { [_book release]; _book = [book retain]; } } - (BFBook *)book { return _book; }Copy the code
  • copy

The operation of copy is very similar to retain. But the object copy, as for the copy after the creation of a new object, or passed in the original object reference count increment 1, need to depend on the situation, this part of the memory management (5) copy more detail.

- (void)setName:(NSString *)name { if (_name ! = name) { [_name release]; _name = [name copy]; } } - (NSString *)name { return _name; }Copy the code
  • unsafe_unretained

Unsafe_unretained and assign is similar, but can be used across object types. It doesn’t affect the reference count of the passed object, and only allows simple assignment.

- (void)setPen:(BFPen *)pen { if (_pen ! = pen) { _pen = pen; } } - (BFPen *)pen { return _pen; }Copy the code

1.4 applications

Forgetting release can cause a memory leak.

- (void)test {BFPerson *person = [[BFPerson alloc] init]; }Copy the code

Here is a more complex use:

- (void)test2
{
    BFBook *book = [[BFBook alloc] init];   //book: 1
    BFPerson *person1 = [[BFPerson alloc] init];  //person: 1
    
    person1.book = book;     //book: 2
    person1.book = book;     //book: 2
    person1.book = book;     //book: 2
    
    NSLog(@"%ld", [book retainCount]);
    [book release];     //book: 1
    [person1 release];  //book: 0
}
Copy the code

Second, the ARC

ARC, Automatic Reference Count, is a decent version of MRC, OC developers no longer like C developers, to the pointer complaints deep, the operation of the Reference Count is automatically managed by ARC.

ARC did some work for us, in two main parts:

  • Compile time: At compile time, the compiler analyzes the life cycle of each object in the source code and adds reference counting operation code based on that object’s life cycle.
  • RuntimeandRunLoopThe two work together to ensure that weak references and auto-release pools work smoothly, and to optimize the program.

2.1 __strong

2.2 __weak

2.3 __unsafe_unretained

2.4 @perperty

The nature of the property remains the same, because reference counting, the foundation of memory management, remains the same.

Three, the Core Foundation

Even with ARC, which is everywhere, it’s still out of reach — Core Foundation.

CF objects in the Core Foundation framework, as well as NS objects in Foundation, are converted by Toll-free Briding technology.

Here is an example of the conversion, in –ARC:

__bridge_retained // This is equivalent to the CFBridgingRetain function. Across retained // an OC pointer is converted to a CF pointer and ownership is transferred. Need to manually call CFRelease object to release the CF nsstrings * s1 = [[nsstrings alloc] initWithFormat: @ "HelloHelloHelloHelloHello"]. CFStringRef s2 = (__bridge_retained CFStringRef)s1; // or CFStringRef s2 = (CFStringRef)CFBridgingRetain(s1) // do something with s2 //2.__bridge_transfer // Equivalent to CFBridgingRelease, a CF pointer is converted into an OC pointer and ownership is transferred. ARC is responsible for managing the life cycle of the OC pointer. CFStringRef s3 = CFStringCreateWithCString(kCFAllocatorDefault, "abc", kCFStringEncodingEUC_CN); NSString *s4 = (__bridge_transfer NSString *)s3; NSLog(@"%ld",(long)s4.length); CFRelease(s3); //3.__bridge // Convert between OC pointer and CF pointer, no object ownership conversion is involved, the original CF object needs to call CFRelease to release the object. NSString * s5 = [NSString stringWithFormat:@"%ld",random()]; CFStringRef s6 = (__bridge CFStringRef)s5; NSLog(@"%ld",(long)CFStringGetLength(s6)); CFStringRef s7 = CFStringCreateWithFormat (NULL, NULL, CFSTR("%d"), rand()); NSString *s8 = (__bridge NSString *)s7; NSLog(@"%ld",(long)s8.length); CFRelease(s7); CFRelease(s7); }Copy the code

Four, mixed

Xcode supports MRC and ARC mixing, as long as you specify the corresponding source file, the specified keywords are: -fno-objc-arc and **-fobjc-arc**.

4.1 Enabling ARC in MRC

4.2 Enabling MRC in ARC

reference

link

  1. Automatic Reference Counting
  2. Memory Management Programming Guide for Core Foundation
  3. Transitioning to ARC Release Notes

The sample code

  1. MRC- Reference counting
  2. ARC