Memory management of Objective-C

Time:2020-9-8

Memory management is a process in which a program allocates memory, uses memory, and releases memory when the program is finished. In Objective-C, it is also seen as a way to allocate ownership of limited memory resources among a large number of data and code.

Memory management is concerned with cleaning up or Reclaiming unused memory so that it can be reused. If an object is no longer in use, you need to free the memory occupied by the object. Objective-C provides two methods of memory management: manual memory counting (MRR) and automatic reference counting (ARC). Both methods are implemented using a model called “reference counting”, which is provided by the nsobject class of the foundation framework and the runtime environment. Next, let’s first introduce what reference counting is.

1 reference count

Reference count is a simple and effective way to manage the life cycle of an object. The general concept is: when a new object is created, the initial reference count is 1. To ensure the existence of an object, whenever a reference is created to the object, theretainMessage, plus 1 to the reference count; when the object is no longer needed, it is sent to the object byreleaseWhen the reference count of an object is 0, the system will know that the object is no longer in use and send it to the objectdeallocMessage, destroy the object and reclaim memory. In general, theretainAfter the method, the reference count is also commonly referred to as the retain count.

Memory management of Objective-C
To better illustrate the mechanism of reference counting, here
An example of switching on and off room lights is given

Assuming that there is only one lighting device in the office, people entering the office need lighting and those leaving the office do not need lighting. Therefore, in order to ensure that the only lighting equipment in the office is well managed, as long as there are people in the office, the lighting will be on, and when there is no one in the office, the light needs to be turned off. In order to determine whether there are still people in the office, we import the counting function to calculate the “number of people who need lighting”:

  • The first person to enter the office needs lighting. At this time, the “number of people who need lighting” is 1, the count value changes from 0 to 1, and the lamp needs to be turned on.
  • The second person entering the office also needs lighting. At this time, the “number of people who need lighting” is 2, and the count value changes from 1 to 2.
  • After that, everyone who enters the office needs lighting. At this time, the “number of people who need lighting” increases in turn, and the count value increases by 1.
  • When the first person leaves the office, lighting is no longer needed. At this time, the number of people who need lighting is reduced by 1, and the count value is also reduced by 1.
  • After that, as long as someone leaves the office, there is no need for lighting. At this time, “the number of people who need lighting” decreases in turn, and the count decreases by 1.
  • When the last person leaves the office, no one needs lighting. The “number of people who need lighting” is 0. The count is reduced to 0 and the lights need to be turned off.

In Objective-C, objects are equivalent to office lighting, and the environment in which objects are used is equivalent to people entering the office to work. The corresponding relationship can be expressed in the following table:
What people do with lighting when they enter the office

The action of the object’s usage environment on the Objective-C object

What people do with lighting when they enter the office The action of the object’s usage environment on the Objective-C object
turn on the light Build object
Lighting is needed Holding object
Lighting is no longer needed Release object
Turn off the lights Destroy object

2 manage memory MRR manually

Manual memory management, namely MRR (manual retain release), is based on reference counting. It can manage memory clearly by tracking objects. The only difference between it and arc is that in MRR, the retention and release of objects are handled manually, while in arc, they are handled automatically.

2.1 basic principles of MRR memory management

For the convenience of understanding, let’s take a look at how the memory management in MRR works through an example, and then we will have a summary.

Open it firstXcode, create a new project(File\New\Project…)Here we write the project name asMemoryManagementDemo。 To ensure that our code is in the MRR environment, we need to check whether arc is enabled in the current project before any operation, and if so, close it, as shown in the following figure:
Memory management of Objective-C

Let’s summarize the rules for manually managing memory:

  • withallocnewcopyormutableCopyWe have the object created by the method at the beginning, and we need to call thereleaseorautoreleaseRelease.
  • stayinitMethod to obtain ownership of an object or, in some cases, to avoid the object being removed, you can use theretainKeep the object. After using the object, you need to use thereleaseRelease.
  • Yes, I didretaincopymutableCopyallocornewMethod, and any object withretainandcopyAttribute, which needs to be overriddendeallocMethod to release these instance variables when the object is released.
  • Send to objectreleaseThe message does not necessarily destroy the object immediately. Only when the reference count of the object is reduced to 0, the object will be destroyed and sent by the systemdeallocThe message is given to this object to free its memory.
  • If you no longer need to use an object in a method, but need to return it, you can send it to the objectautoreleaseMessages are used to mark delayed releases, and the reference count of the object is subtracted by 1 at the end of the current auto release pool.
  • When the application terminates, all objects in memory are released, whether they are in the auto release pool or not.
  • When an object is no longer needed, ownership of the object must be relinquished.
  • You can’t give up ownership of an object you don’t own.

2.2 auto release pool

The automatic release is mentioned above. Here we briefly introduce the automatic release pool.

The purpose of automatic release pool creation is to help track the objects that need to be released after some time delay.
By sendingautoreleaseMessage, you can add an object to the list of objects maintained by the autorelease pool:

[object autorelease];

When using classes from foundation, UIKit and AppKit frameworks in a program, you need to create an auto release pool first, so that classes from these frameworks can create and return automatically released objects, which need to be used in the program@autoreleasepoolInstructions (usually in the projectmain.mYou will see the statement in the file:

@autoreleasepool {
    statements
}

When executed to the end of the autorelease block, the system sends areleaseMessage, which will affect all sentautoreleaseMessages are added to the auto release pool of objects that are sent when their reference count drops to 0deallocMessages, and their memory will be freed.

It should be noted that the auto release pool does not contain the actual object, but only contains the reference of the object. The object will be released when the auto release pool is cleaned. In arc, the automatic release pool is mainly used to reduce the memory peak, but we don’t need to add it manuallyautoreleaseOf the code.

2.3 using accessor method to simplify memory management

When managing memory manually, useretainorreleaseIn order to keep or release objects, it is inevitable to make mistakes. Therefore, we can use accessor method to reduce the problems in memory management.

Generally speaking, accessor methods refer to setters and getters, which are also called access methods. Setting value method is the method to set the value of instance variable. The main purpose is to set the method parameter to the value of the corresponding instance variable. Generally, no value will be returned. The value method is the method to retrieve the value of instance variable. The main purpose is to obtain the value of instance variable stored in the object and send it through program return. Therefore, the value method must return the value of instance variable as the return parameter.

Let’s continue with the previous example in theTableViewController.hAdd setting method and value method for two instance variables in the file:

@interface TableViewController : UITableViewController
{
    NSArray *_titles;
    NSString *_lastTitleSelected;
}

- (void)setTitles:(NSArray *)titles;
- (NSArray *)titles;
- (void)setLastTitleSelected:(NSString *)lastTitleSelected;
- (NSString *)lastTitleSelected;

@end

And then in theTableViewController.mAdd the implementation method at the bottom of the file

#pragma mark - Accessor method

- (void)setTitles:(NSArray *)titles
{
    [titles retain];
    [_titles release];
    _titles = titles;
}

- (NSArray *)titles
{
    return _titles;
}

- (void)setLastTitleSelected:(NSString *)lastTitleSelected
{
    [lastTitleSelected retain];
    [_lastTitleSelected release];
    _lastTitleSelected = lastTitleSelected;
}

- (NSString *)lastTitleSelected
{
    return _lastTitleSelected;
}

The getter methods above are easy to understand, they only return instance variables. In the setter method, we first use theretainKeep the newly passed in parameter variables to increase the reference count, and then use thereleaseRelease the old instance variable to reduce the reference count, and finally set the value of the instance variable to the parameter variable passed in. In this way, as long as you set the object, you can ensure that the object stored in the instance variable has the correct reference count. In addition, setting instance variables in this order can prevent setting instance variables to the same object. In addition, if you observe the above setting method carefully, you will understand the reason why we used underline when naming instance variables. The main reason is to avoid conflicts caused by the same name of instance variable and parameter variable.

Next, we use these access methods to modify instance variables in the code.

First, we use the set value method to modify itviewDidLoadMedium_titles

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self setTitles:[[[NSArray alloc] initWithObjects:@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", nil] autorelease]];
}

If you look carefully, you will find that in addition to using the setting method, we also call theautorelease。 Remember we used the setter methodretainAdd 1 to the passed in parameter variable reference count? Here we use itinitWithObjects:Creating an array object will result in a variable with a final reference count of 2. Therefore, automatic release must be used to reduce the reference count. Of course, we can also use itarrayWithObjects:Method to create an array object so you don’t need to call it againautoreleaseYes.

In addition, for convenience, Objective-C allows us to use dot operators.Replace square brackets[]To set or get the value of the instance variable

self.titles = xxx;

amount to:

[self setTitles:xxx];

dot operator .Commonly used for attributes, but not limited to attributes.

Let’s use the dot operator.Modify the above method again:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.titles = [[[NSArray alloc] initWithObjects:@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", nil] autorelease];
}

The next step istableView:didSelectRowAtIndexPathMethod_lastTitleSelected

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    ...
    
    //Create an alert view to display pop-up messages
    ...
    [self presentViewController:alert animated:YES completion:nil];
    
    //Set instance variable (delete the last two lines of code and replace it with the following code)
    self.lastTitleSelected = title;
}

We have written the memory management code of instance variables in thesetterMethod, so it is much easier to set instance variables in the above code.

In addition, it is mentioned in the document that the accessor method should not be used in the initialization method and dealloc method

The only places you shouldn’t use accessor methods to set an instance variable are in initializer methods and dealloc.

If you want to be ininitMethod is used to initialize an object in the following form:

- (instancetype)init
{
    self = [super init];
    if (self) {
        instance = ...
    }
    
    return self;
}

staydeallocInstance variables should also be used in the method:

- (void)dealloc
{
    [instance release];
    [super dealloc];
}

The reason why I said not to be ininitanddeallocThe use of accessor method is mainly due to the combination of object-oriented inheritance, polymorphism and possible side effects of accessor method. Inheritance and polymorphism cause calls to the accessor method in the implementation of the parent class, which may be called to the subclass rewriting access method. The subclass is not completely initialized or destroyed, resulting in confusion, resulting in a series of logical problems and even collapse. But this statement is not absolute. Although there are risks, it does not mean 100% crash or error. If you write this in the program and you know that it will not cause any problems, you can use it to simplify your code. For example, here we modify itdeallocCode in:

- (void)dealloc
{
    self.titles = nil;
    self.lastTitleSelected = nil;
    
    [super dealloc];
}

The above two lines of code that manually call release and set it to nil are deleted, and then use the setter method instead. Now we pass nil as a parameter variable in the value setting method

[nil retain];
[_titles release];
_titles = nil;

Because of the[nil retain]Nothing will be done, so we are in thedeallocMethodself.titles = nilThere will be no problems. However, for the sake of safety, we recommend that you follow the instructions in the documentation when it is not clear if there will be a problem.

2.4 use properties

In addition to manually writing access methods, Objective-C also provides properties that allow us to quickly create accessor methods for instance variables and implement them as an option.

Property is generally declared in the interface section to@propertyKeyword, then you can selectively define the properties of the property, and then end with the type and name of the property (we usually use the same name as the instance variable, but not required). Here are several valid attribute declarations:

@property int age;
@property (copy) NSString *name;
@property (nonatomic, strong) NSArray *array;

Note that when you declare a property, do not precede the name of the property with thenewalloccopyperhapsinitThese words begin.

To declare a property is equivalent to declaring setter and getter methods, andageFor example:

@property int age;

It is equivalent to:

- (void)setAge:(int)age;
- (int)age;

The default setting method name of the general system is as followssetSet propertyname, the default value method is named by the property name (propertyname). If you want to change to a custom name, you can use the following methods:

  • Use setter = settername to specify the name of the setter method, such as:
@property (setter = setterName) int age;
  • Use getter = gettername to specify the name of the getter method, such as:
@property (getter = getterName) int age;

Commonly used inBOOLType, the getter method usually takes theisStart, such as identifying whether a view is hiddenhiddenProperty whose getter method should be calledisHidden。 It can be stated as follows:

@property (nonatomic,getter = isHidden ) BOOL hidden;

Next, we use the@synthesizeTells the compiler to automatically implement a value setting method and a value taking method for an attribute

@implementation Class

@synthesize age;

@end

among@synthesize ageBy default, the instance variable name specified is the same as the property, that is:

@synthesize age = age;

After Xcode 4.4, the compiler introduced the property autosynthesis, which means that the compiler will provide each@propertyadd to@synthesizeWe don’t need to use it explicitly any more@synthesizeYes. However, it should be noted that the default generated instance variable names are automatically synthesized to_Is the prefix, plus the attribute name, that is:

@synthesize age = _age;

If you don’t like the default instance variable name, or if we want to use a more semantic name, we need to use the@synthesizeTo specify the name after the equal sign as the instance variable name we want:

@synthesize age = currentAge;

It should also be noted that usually the compiler will automatically synthesize an instance variable and at least one accessor method, if we use thereadwriteKeyword property implements both setter and getter methods manually, orreadonlyKeyword’s property implements the getter method, and the compiler assumes that we are controlling the implementation of the property and will not automatically synthesize instance variables. In this case, we need to manually specify an instance variable:

@synthesize property = _property;

In addition, it should be noted that it is generally used@propertyAccess methods will be synthesized automatically during compilation, but some access methods are created dynamically at runtime. In this case, a warning will be issued during compilation due to the lack of methods when declaring and using properties. In this case, we can use the@dynamicStatement to suppress warnings:

@implementation Class
@dynamic age;
@end

Let’s replace the access method in our code with properties:

First of all, we are inTableViewController.hDelete the declaration of instance variables and access methods in the file, and use attributes instead of:

@interface TableViewController : UITableViewController

@property (nonatomic, retain) NSArray *titles;
@property (nonatomic, retain) NSString *lastTitleSelected;

@end

Then switch toTableViewController.mFile, delete the setter and getter methods previously written, and add them at the top of the implementation section@synthesize

@implementation TableViewController

@synthesize titles = _titles;
@synthesize lastTitleSelected = _lastTitleSelected;

Of course, the instance variables declared here are consistent with the default values, so the@synthesizeIt can also be omitted.

Now you can run the code to try, you will find that the emulator is as normal as before. However, it is obviously much simpler and more efficient to let the compiler automatically generate access methods than we manually write access methods. Moreover, it can be run on multi-core devices using multithreading.

2.5 characteristics of attributes

Property uses special keywords to tell the compiler how to compose the relevant accessor methods. In our code, we use thenonatomicandretain。 Previously, when we talked about the declaration of properties, we also used it in the examplecopyHowever, the keywords of attributes are more than these. They are generally divided into thread related, accessor related and memory related. Here is a detailed introduction.

2.5. Atomic threads

Atomic (default)

  • Default attribute. If no attribute is specified with any key, the attribute of Objective-C attribute is by defaultatomic
  • atomicRepresents the atomic attribute. This attribute is used to tell the system how to use mutex lock to protect the access method of the attribute. If the current process is halfway through and other threads access the current thread, it can ensure that the current thread is executed first. In other words, even if the accessor method is called from different threads at the same time, it can ensure that a value can always be fully retrieved by the getter method or completely set by the setter method. For example, in a multithreaded program, if multiple threads point to the same instance variable, one thread can read and the other can write. When they are clicked at the same time, the read thread is guaranteed to get a valid value, either before or after the change.
  • Atomic properties are different from object thread safety, and the use of atomic properties does not guarantee thread safety. If multiple threads access the same instance variable at the same time, one of the threads callsreleaseWill cause the program to crash.
  • useatomicThe mutex lock code generated by the compiler will cost a lot of resources, slow down the program and affect the efficiency, so it is rarely used.
  • atomicProperty composition accessor methods are private, so they cannot be combined with their own implemented accessor methods. If we try toatomicProperty provides a custom setter or getter method and receives a warning from the compiler:

Memory management of Objective-C

Memory management of Objective-C
nonatomic

  • nonatomicAndatomicInstead, it represents a non atomic property. This property is used to tell the system not to use mutex lock to protect the access method of the property. When multiple threads access the same property at the same time, it will lead to unpredictable results. There is no guarantee that a valid value will be returned when the accessor method is called. If we try to read in the middle of a write, we may get an invalid value.
  • FollowatomicBy comparison,nonatomicIf you want to access a property multiple times, use thenonatomicIt will be more efficient.
  • Generally, it is widely used in the case of single thread and knowing that only one thread can access it.
  • usenonatomicYou can combine automatically synthesized setter or getter methods with your own manually implemented getter or setter methods. Therefore, for the use ofatomicWhen you implement a setter or getter, you can set the attribute of the property tononatomicTo release:

Memory management of Objective-C

2.5.2 accessor related: readonly and readwrite

readonly

  • readonlyRepresents a read-only property that is read-only for all classes, including itself.
  • The synthesized accessor has only getter methods and no setter methods.

Readwrite (default)

  • The default attribute, which generally does not need to be explicitly declared.
  • readwriteRepresents the read-write property, that is, the property can be read and written by itself or other classes, andreadonlycontrary.
  • The synthesized accessor has both setter and getter methods.

If you want a property to be read-write only to itself and read-only to other classes, you can set the.hIn the interface section of the file, declare the attribute of the property asreadonlyAnd then in the.mThe private interface part of the file redeclares the attribute attribute asreadwriteThat’s fine.

2.5.3 memory related: retain, assign, strong, weak, copy, unsafe_ unretained

retain

  • retainThe number of objects that are passed in is used to increase the ownership of the object.
  • Use in propertiesretainKeyword can instruct the compiler to keep the passed in variables before setting instance variables. In the default setting method, it will be:
   if (_property != newValue) {
       [_property release];
       _property = [newValue retain];
   }
  • It is mainly used in manual memory management. Under arc, it is generally usedstrongreplace.

Assign (default)

  • Default properties. General imageintfloatdoubleandNSIntegerCGFloatBOOLAttributes of equivalent type are used by defaultassign
  • assignIt is used for the assignment operation of property. There is no ownership relationship. In the default setting method:
   _property = newValue;

copy

  • copyUse to create a copy of an object and have ownership of the replica object, not the original object itself.
  • Use in propertiescopyKeyword to instruct the compiler to create a copy of the incoming variable before setting the instance variable. In the default setting method, this will be:
   if (_property != newValue) {
       [_property release];
       _property = [newValue copy];
   }
  • copyProperty to implicitly strong reference the replica object it creates. It also means that the property will use thestrongBecause it must keep the replica object it created.
  • bycopyAny object set by theNSCopyingagreement.
  • If you need to set it directlycopyProperty, for example, in initialization methods, remember to set a copy of the original object.

Strong (default)

  • Default properties. In general, the default properties of Objective-C objects arestrong
  • strongIt is the keyword introduced when arc is introduced, which is equivalent to MRRretain
  • usestrongDeclare a strong reference, indicating that the instance variable owns the ownership of the object passed in. As long as the reference of the object in the attribute is held, the object will not be released. If two strongly referenced objects point to each other, a strong reference loop will occur.
  • In Objective-C, the object properties arestrong, and the object variable is by default__strong

weak

  • weakIt is also an attribute keyword under arc, but it is introduced from IOS 5, so it is not available before IOS 5.
  • useweakDeclare weak references, andstrongInstead, it means that the instance variable has no ownership of the incoming object, and the reference count is not increased on the incoming object in the setter method. When the object is released, the instance variable is automatically set to nil.
  • For variables, we can use__weakThe variable is declared as a weak pointer variable, and in practical application, we also use the__weakReplace strong reference with weak reference to solve the problem of strong reference loop
 NSObject * __weak weakVariable;
  • In general, delegate and outlet useweakTo declare.

unsafe_unretained

  • unsafe_unretainedRepresents an unsafe reference, which was replaced before IOS 5weakKeywords for.
  • AndweakThe difference is, useunsafe_unretainedWhen the object is released, the instance variable is not automatically set to nil. This means that we will leave a hanging pointer pointing to the memory occupied by the previously released object, which will cause the program to crash, so it is called “unsafe”.

2.6 problems to be avoided in memory management

There are two main problems caused by incorrect memory management

  • Releasing or rewriting memory that is still in use leads to memory corruption: it usually leads to application crash, and even causes user data to be rewritten or damaged.
  • Failure to free memory that is no longer in use leads to memory leaks: it can cause applications to use more memory, resulting in system performance degradation or application termination.

For the first problem above, we can use the nszombieenabled debugging tool to find over released objects. For the second problem, you can use instruments to track reference count events and look for memory leaks.

If you want to identify problems in your code at compile time, you can use the built-in static analysis function in Xcode. This will cause Xcode to run our code and look for any errors that can be detected automatically to warn us of any potential problems. Next, we will use this function for previous projects to detect whether there are problems:

Open the project and select from the menu bar at the topProduct\Analyze
Memory management of Objective-C
Memory management of Objective-C

The above message tells us that a memory leak has been detected, instance variables_windowNeed to be released, lackdeallocMethod, so we are in theAppDelegate.mThe implementation part ofdeallocMethod, and the instance variable_windowcallreleasemethod:

- (void)dealloc
{
    [_window release];
    _window = nil;
    
    [super dealloc];
}

Click again in the menu barProduct\AnalyzeYou’ll see that the previous tags disappear and no new problems are detected.

3 automatic reference count arc

Automatic reference counting, or arc (automatic reference counting), is a new feature of Xcode 4.2. It uses the same reference counting system as manual management. The difference is that the system will help us insert appropriate memory management methods at compile time. Retention and release are automatically processed, thus avoiding some potential pitfalls of manual reference counting. It is generally recommended in new projects.

3.1 rules of memory management under arc

The rules of arc are very simple. We don’t need to keep and release objects manually. All we need to do is manage the pointers to the objects. As long as there is a pointer to the object, the object remains in memory; when the pointer points to another object, or does not exist, the object is automatically released.

Here are the rules for memory management in arc

  • Cannot be explicitly calleddealloc, orretainreleaseretainCountautoreleaseEtc. can’t even be used@selector(retain)@selector(release)Etc.
  • If you need to manage resources other than releasing instance variables, you can implementdeallocMethod, and customdeallocMethod does not need to be called[super dealloc]
  • The name of an accessor method cannot benewAt the beginning, this in turn means that you cannot declare anewUnless we specify a different getter:
//Error:
@property NSString * newTitle;

//Correct:
@property(getter = theNewTitle)NSString * newTitle;

3.2 conversion of MRR to arc

In the demo above, we all use MRR to manage the memory. Now we need to convert it to arc. The easiest way to think of is to convert it manually. All calls to theretainreleaseThe code of the method is removed, but it is troublesome to do so. Fortunately, Xcode provides an arc automatic conversion tool, which can help us easily convert the source code to arc. What’s more flexible is that it can not only convert all files in the project to arc, but also selectively convert specified files. For some files that do not want to be converted, arc can be disabled.

Now we use this automatic conversion tool to convert our code:

First of all, arc is a feature of llvm3.0 compiler, so let’s first confirm whether the current compiler conforms to. Select the item in the file and select theBuild SettingsEnter “compiler” in the search box, and thenBuild OptionsView the first item in theCompiler for C/C++/Objective-CCorresponding compiler version:
Memory management of Objective-C
Before we convert, we clickXcodeIn the menu barProduct\BuildTo ensure that there is no problem with the current code.

Next fromXcodeFrom the menu barEdit\Convert\To Objective-C ARC…
Memory management of Objective-C
Then in the pop-up window, click the small triangle under the first icon to expand all the files. Here, to compare the manual conversion, we deselect itAppDelegate.mFile, select only the other two files selected by default for conversion, and then clickcheck
Memory management of Objective-C
Continue to click in the pop-up windowNext
Memory management of Objective-C
You will see that the transformation is being generated:
Memory management of Objective-C
After the conversion is complete, a preview of all files will be displayed. The left pane shows the changed file and the right pane shows the original file. Here’s what’s shown hereTableViewController.hFile, you will see that thestrongInsteadretain
Memory management of Objective-C
Next we switch toTableViewController.mDocument:
Memory management of Objective-C
There are two changes here. The first is in theviewDidLoadMethod, initializetitlesDeleted whenautoreleaseCall to. And then deleted itdeallocMethods and contents.

After confirmation, continue to clickSaveSave the changes, you can see the changes of the preview file in our project, and the conversion is completed.

Compile the program again and clickProduct\Build, showing that the compilation was successful.

It is also important to know that it is possible to combine arc code with non arc code in the same project. Now let’s open itAppDelegate.mFile, you will see that the file still existsdeallocThis is because the conversion tool has disabled the arc of the two source files when we deselect the file. We can use theTARGETSOfBuild PhasesWe can see that:
Memory management of Objective-C
AppDelegate.mThe document has been added-fno-objc-arcTo indicate that the file will not be compiled using arc rules. Conversely, if you want to enable arc for a particular file, you can add it-fobjc-arcMark. Here, we double-clickAppDelegate.mAfter the file, change it to-fobjc-arcTo enable arc for this file:
Memory management of Objective-C
Click againProduct\BuildWhen compiling the program, you will see an error prompt. Let’s manually change the code to fix these errors:

Open it firstAppDelegate.mFile, see the error mainly occurred indeallocIn the method
Memory management of Objective-C
From the error message, we can see that it is mainly due to the call under arcreleaseanddeallocCaused by. We delete the wholedeallocMethod, the error disappears, and click againProduct\BuildCompiler, compiled successfully. At this point, run the program, you will find that everything is normal.

At this point, our conversion work has been completed, and all files in the project use arc. If you still have problems with the code, you can download the memory management demo to view it.

4. Memory management of core foundation objects

4.1 Core Foundation

Core foundation is a foundation framework based on Objective-C, but it is implemented in C language. For most applications, we don’t need to use core foundation. Generally, we can do whatever we want from Objective-C. However, for some underlying APIs, such as core graphics and core text, we need to know something about core foundation.

Most of the underlying core foundation objects areCreateWithThe first function is created, and its memory management only needs to continue the manual reference counting method. To modify the reference count, you need to use theCFRetainandCFReleaseFunction, whose function is similar to that of Objective-C objectretainandreleaseThe method is similar.

//Create a cfstringref object
    CFStringRef cfString = CFStringCreateWithCString(kCFAllocatorDefault, "string", kCFStringEncodingUTF8);
    
    //Keep the object and add 1 to the reference count
    CFRetain(cfString);
    
    //Release the object and subtract the reference count by 1
    CFRelease(cfString);

4.2 toll free bridged

There are many data types that can be used interchangeably between the core foundation framework and the foundation framework. For example, we can use theNSStringObject to use as aCFStringRefYou can also use theCFStringRefObject to use as aNSString。 This interchangeable data type is also known as the free bridge data type. This means that we can use the same data structure as the parameters of the core foundation function call or the receiver of the Objective-C message call. However, not all data types are bridged for free. For a detailed list, please refer to toll free bridged types.

In free bridging, an important issue related to memory management is the ownership of objects in the conversion process. For example, under arc, we need to convert a core foundation object into an Objective-C object. At this time, we need to tell the compiler how to manage the ownership of the object. Therefore, we introduce the key words related to bridge to explain the ownership semantics of objects

4.2.1 __bridge

use__bridgeYou can convert between Objective-C objects and core foundation objects. This conversion only does type conversion and does not transfer the ownership of objects.

  • use__bridgeConvert the Objective-C object to the core foundation object, and release the object after using it
//Create an nsstring object
   NSString *nsString = @"string";
   
   //Convert nsstring object to cfstringref object
   CFStringRef cfString = (__bridge CFStringRef)nsString;
  • use__bridgeTo convert a core foundation object to an Objective-C object, you need to callCFReleaseRelease object:
//Create a cfstringref object
   CFStringRef cfString = CFStringCreateWithCString(kCFAllocatorDefault, "string", kCFStringEncodingUTF8);
   
   //Convert cfstringref object to nsstring object
   NSString *nsString = (__bridge NSString*)cfString;
   
   //Release cfstringref object
   CFRelease(cfString);
4.2.2 __bridge_retained

use__bridge_retainedorCFBridgingRetainConvert the Objective-C object to the core foundation object. This conversion will transfer the ownership of the Objective-C object to the core foundation object. After using it, you need to callCFReleaseRelease object ownership.

//Create an nsstring object
    NSString *nsString = @"string";
    
    //Convert nsstring object to cfstringref object
    CFStringRef cfString = (__bridge_retained CFStringRef)nsString;
    
    //Release cfstringref object
    CFRelease(cfString);
4.2.3 __bridge_transfer

use__bridge_transferorCFBridgingReleaseConvert the core foundation object to Objective-C object. This conversion will transfer the ownership of the core foundation object to arc, and the arc is responsible for releasing the ownership of the object after use.

//Create a cfstringref object
    CFStringRef cfString = CFStringCreateWithCString(kCFAllocatorDefault, "string", kCFStringEncodingUTF8);
    
    //Convert cfstringref object to nsstring object
    NSString *nsString = (__bridge_transfer NSString*)cfString;

5 references

Advanced Memory Management Programming Guide

Encapsulating Data

Transitioning to ARC Release Notes

Obj-C Memory Management

Memory Management Tutorial for iOS

Properties Tutorial for iOS

Beginning ARC in iOS 5 Tutorial

Second hand dynamic memory management of memory management

Understanding memory management of IOS

Recommended Today

Explain idea git branch backoff specified historical version

scene When I submitted this modification to the local and remote branches, I found that there were still some changes missing in this submission, or this modification was totally wrong, but I also pushed it to the remote repository. How to go back? problem How can the content that has been submitted to the repository […]