App memory management from MRC to ARC scheme

The purpose of,

Before ARC(Auto Reference Counting), iOS memory management is a headache for both experienced developers and novices. During the development process, it is inevitable to write code with memory leakage, and developers have to spend a lot of time on memory management. Even so, a memory leak or release of a freed object can still cause a crash. Now That Apple has introduced ARC for iOS/Mac OS development, developers no longer need to manually retain Release autorelease. The compiler automatically inserts the corresponding code where appropriate and implements the automatic reference counting in combination with the Object-C Runtime mechanism.

Two, ARC scope of application

1. Type of ARC applicable

  • Block (ARC already manages GCD objects)
  • Objective object, ID, Class, NSError… Etc.
  • The type marked by attribute((NSObject))

2. ARC is not applicable

  • likedouble * CFStringRefIf ARC is not applicable, you still need to manually manage memory notes * that start with CFCore FoundationObjects often require manual memory management

Third, the conversion process

1. Code backup

Before making major changes, we need to make code backups

2. Filter code

  • Find third-party libraries referenced in the project that still use manual memory management, or files you don’t want converted, and add them-fno-objc-arctag
  • The Xcode automatic conversion tool only works with Objective-C objects, and only works with objective-C /Objective-C++ files with the suffix.m/.mm. Therefore, other C/C++ files with the suffix.c/.cpp are not needed

3. Perform the check operation

Edit->Convert->To Objective-C ARC

check

-fno-objc-arc: “-fno-objc-arc:” -fno-objc-arc: “-fno-objc-arc:” -fno-objc-arc: “-fno-objc-arc:” -fno-objc-arc: “-fno-objc-arc:” -fno-objc-arc: “-fno-objc-arc:”

Common errors and warning solutions

specification

1. Methods must be named in accordance with the naming rules. Methods that start with Alloc init new Copy mutableCopy are not allowed to be arbitrarily defined. ** You might inadvertently use method names that start with new or copy, such as newLine for a newLine method, copyRight for a copyrighted method, and so on. These names are incorrect, may cause a release, and may prompt warnings or errors at compile time. Therefore, remember to adhere to the memory management related function naming rules. When you’re not using ARC, you might not name your methods according to the naming conventions in ARC, and in that case, if for some reason you can’t change the names of those methods, then migrating the code to an ARC environment will be a problem. This is done by adding predefined macros to the method to tell the compiler how to manage the return value of the method. For example, NS_RETURNS_RETAINED specifies that like init or copy, the calling end is responsible for releasing the returned object. NS_RETURNS_NOT_RETAINED specifies that this method is not a memory management method. The caller does not need to release the returned object. The following methods

+ (FinishingDate*)newMoon NS_RETURNS_NOT_RETAINED;
Copy the code

Although it is a method that starts with new, the macro that follows tells the compiler that this is the return value of the method and does not need to be released on the calling side. At compile time, these macros are replaced with annotations. These macros are defined in nsobJCruntime.h. Such as:

-(MRCTest*)NewMRCTestFun NS_RETURNS_NOT_RETAINED;
Copy the code

After Preprocess:

-(MRCTest*)NewMRCTestFun __attribute__((ns_returns_not_retained))
Copy the code

You can also determine if ARC is valid by conditional compilation if:

#if __has_feature(objc_arc)
Copy the code

If true, ARC is valid, otherwise ARC is invalid. In ARC, if -(void)dealloc; It is still executed, but the [super dealloc] method is not called when dealloc is overwritten. 3. Use @autoRelease instead of NSAutoreleasePool. 4. There are two kinds of objects in the iOS world: Objective-C objects and Core Foundation objects. Objects of Core Foundation type are not managed by ARC. Therefore, when converting these two types, you tell the compiler how to handle object ownership. For the same reason, ARC programs cannot convert the id and void * types, even with the __unsafe_unretained modifier. You can convert them to each other using the _bridge modifier.

error

Error: ARC Forbids Objective-c obj in structs or unions Reason: You cannot define Objective-C objects in C constructs or Commons with ARC in effect. The reason is that the compiler cannot automatically free objective-C objects inside a structure (or Commons). Solution: Use Objective-C classes instead of constructs or Commons. If a structure must be retained for efficiency or other reasons, you can use the __unsafe_unretained modifier to modify objective-C variables within the structure. This way, the compiler does not manage the variable’s memory, so you need to manage the memory completely manually. ARC Forbids synthesizing a property of an Objective-C object with unspecified ownership or storage attribute The property property must specify a memory management key. Solution: Add the strong weak copy keyword to the attribute definition. ARC Forbids Explicit message Send of ‘release’ cause: Usually use macro definitions that include release.

Note: We were unable to automatically convert code that used macros in the previous automatic conversionCopy the code

Solution: Simply remove the macro and where it is used, or remove release from the macro definition. Init methods must return a type related to the receiver type

@interface HomeViewController : UIViewController
- (UILabel *)initLabelWith...
@end
Copy the code

The reason: A method in class A starts with init and returns type B; 5, error: Cast of C pointer type ‘ivPointer’ (aka ‘void’) to Objective-C pointer type ‘iFlyTTSManager_old’ requires a bridged dged novel Cast_pointer_objective-c Cause: Toll-free Bridging conversion problems. Use the corresponding conversion keywords in ARC. Toll-freebridging under MRC does not involve transfers of memory management. Objective-c (OC) and Core Foundation (CF) manage their own memory, and can be directly interchanged with each other. For example:

NSLocale *gbNSLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"];
CFLocaleRef gbCFLocale = (CFLocaleRef)gbNSLocale;
Copy the code

Under ARC, things get a little more complicated. Since ARC can manage the memory of OC objects, but not CF objects,CF objects still need to be managed manually. The problem arises when you bridge an object between CF and OC, and the compiler does not know what to do with an object that has both OC and CF Pointers to it. You need to use __bridge, __bridge_retained, and __bridge_transfer modifiers to tell the compiler what to do.

  • __bridge

It tells the compiler that it is still responsible for managing reference counts on the OC side and the developer that it is still responsible for managing reference counts on the CF side, such as:

CFStringRef cfString = CFStringCreateWithCString(kCFAllocatorDefault, "CFString", kCFStringEncodingUTF8);
NSString *ocString = (__bridge NSString *)cfString;
CFRelease(cfString);
NSLog(@"%@",ocString);
Copy the code
  • __bridge_retainedCFBridgingRetain

They work the same way, just in different ways. The compiler is told that the retain object is needed, and the developer is responsible for releasing it on the CF side. In this way, even if the object is released on the OC side, it will not actually be destroyed as long as the developer does not release the object on the CF side.

NSArray *ocArray = [[NSArray alloc] initWithObjects:@"foggry", nil]; CFArrayRef cfArray = (__bridge_retained CFArrayRef)ocArray; /** CFRelease(cfArray);Copy the code
  • __bridge_transferorCFBridgingReleaseThey work the same way, just in different ways. This keyword tells the compilerbridgeAt the same time, it also transfers the ownership of the object, for example:
CFStringRef cfString = CFStringCreateWithCString(kCFAllocatorDefault, "CFString", kCFStringEncodingUTF8); NSString *ocString = (__bridge_transfer NSString *)cfString; //CFRelease(cfString); NSLog(@"%@",ocString);Copy the code

During the conversion process, you only need to choose the appropriate keywords according to the specific requirements. In addition, id and void * can no longer be converted to each other directly in ARC, and must be modified using toll-freebridging using the appropriate keywords.

Error: ‘NSAllocateObject’ is unavailable: Not available in automatic reference counting mode Cause: If NSAllocateObject is disabled in ARC mode, modify the creation mode

7. Error reporting: Cannot assign to ‘self’ outside of a method in the init family The method returns an ID and the name starts with init+ uppercase + other as a guideline solution: Change the method name

warning

Warning: Capturing self in this block is likely to lead to a retain cycle Reason: This is a typical block loop reference problem; Solution: Change the block self to use the weak pointer to self. Using ‘initWithArray:’ with a literal is redundant cause: alloc is not necessary Property follows Cocoa naming convention for returning ‘owned’ objects Change the name of the corresponding getter method to a non-keyword name:

  • Note: If the method name under ARC starts with new/alloc/init, etc., and it is not an initialization method of the class, you should be careful. You should either report an error or warn, and you know why.

Most likely in this block is likely to lead to a retain cycle reason: Obvious block causes cyclic reference memory leak solution: weakSelf

Xcode automatically converts

Keyword conversion

  • Retain automatically changes to strong
  • The assign keyword was changed to weak
  • The assign keyword that modifies objective-C objects or ID objects is converted to weak. However, the assign keyword that modifies numeric variables such as Int/bool is not automatically converted to weak

Keyword deletion

  • And manual memory management related to several key words, such as: release/retain/autorelease/super dealloc etc. Will be deleted;
  • If there is any code in the dealloc method other than the Release /super Dealloc statement, the dealloc method is retained, otherwise the whole method is deleted

Keyword substitution

  • The block keyword is automatically replaced with weak during conversion.
  • NSAutoreleasePool does not support ARC and is replaced with @autoreleasepool.

Help: Manual Memory Management (MRC) to ARC

Wang Baoxiang, April 2, 2018