一、引用計(jì)數(shù)器
1> 棧和堆
棧
① 主要存儲(chǔ)局部變量② 內(nèi)存自動(dòng)回收
堆
① 主要存儲(chǔ)需要?jiǎng)討B(tài)分配內(nèi)存的變量② 需要手動(dòng)回收內(nèi)存,是OC內(nèi)存管理的對(duì)象
2> 簡(jiǎn)介
作用
① 表示對(duì)象被引用的次數(shù)② 通常由alloc、new、copy與release方法引發(fā)③ 動(dòng)態(tài)監(jiān)測(cè)引用計(jì)數(shù)器的值,當(dāng)值為0時(shí)回收對(duì)象所占的內(nèi)存
使用注意
① 引用計(jì)數(shù)器一個(gè)NSUInteger類型的變量,占用4字節(jié)內(nèi)存② 在對(duì)象被創(chuàng)建的時(shí)候引用計(jì)數(shù)器的值被初始化為1③ 每個(gè)使引用計(jì)數(shù)器加1的操作,都有一個(gè)引用計(jì)數(shù)器減1的操作與之 對(duì)應(yīng)
3> 基本概念
僵尸對(duì)象
① 所占用的內(nèi)存已經(jīng)被回收的對(duì)象② 僵尸對(duì)象不能再被使用
野指針
① 指向僵尸對(duì)象的指針② OC中引用野指針會(huì)報(bào)錯(cuò),錯(cuò)誤信息:EXC_DAB_access
空指針
① 沒(méi)有指向任何內(nèi)存地址的指針② 空指針的值通常為nil、NULL或0③ 通常在創(chuàng)建指針時(shí)將其初始化,避免其指向不確定的內(nèi)存④ 在對(duì)象被銷毀后,通常要將指向?qū)ο蟮闹羔樫x值為nil,避免產(chǎn)生野 指針
4> 基本方法
retain
① 使引用計(jì)數(shù)器加1② alloc、new、copy等方法會(huì)自動(dòng)調(diào)用retain方法③ 每個(gè)retain方法都必須對(duì)應(yīng)一個(gè)release方法④ 返回值為對(duì)象本身
release
① 使引用計(jì)數(shù)器減1② 沒(méi)有返回值③ 用空指針調(diào)用release方法不會(huì)報(bào)錯(cuò)④ 不是經(jīng)過(guò)alloc方法創(chuàng)建的對(duì)象,不需要執(zhí)行release操作
dealloc
① 在對(duì)象被銷毀時(shí)調(diào)用② 通常需要重寫(xiě)dealloc方法③ 重寫(xiě)dealloc方法時(shí),必須在最后調(diào)用父類的dealloc方法④ @PRoperty不會(huì)影響dealloc方法,只會(huì)影響色圖特人和getter
二、多對(duì)象內(nèi)存管理
1> 基本使用
2> set方法的內(nèi)存管理
基本使用
① 當(dāng)set方法的參數(shù)是OC對(duì)象時(shí),通常要在set方法內(nèi)實(shí)現(xiàn)內(nèi)存管理② 當(dāng)參數(shù)與成員變量不一樣時(shí),才對(duì)成員變量執(zhí)行release操作,對(duì) 參數(shù)執(zhí)行retain
set方法的代碼規(guī)范
① 基本數(shù)據(jù)類型:直接賦值② OC對(duì)象類型 1)先判斷是不是新對(duì)象 2)若是,對(duì)就對(duì)象執(zhí)行一次release操作,對(duì)新對(duì)象執(zhí)行一次retain 操作 3)否則,不執(zhí)行操作
dealloc方法的代碼規(guī)范
① 對(duì)self擁有的所有對(duì)象執(zhí)行一次release操作② 一定要調(diào)用父類的dealloc方法,且放在最后③ 在ARC環(huán)境下重寫(xiě)dealloc方法不能調(diào)用父類的dealloc方法
3> @property對(duì)內(nèi)存的影響
基本使用
① 為成員變量生成setter和getter② 默認(rèn)生成的setter執(zhí)行的是直接賦值,不涉及內(nèi)從管理③ 若setter的參數(shù)是OC對(duì)象,需要設(shè)置@property的參數(shù),使其生成 內(nèi)存管理代碼
@property的參數(shù)
① 內(nèi)存管理相關(guān)參數(shù) 1)retain:release舊對(duì)象,retain新對(duì)象(適用于OC對(duì)象類型) 2)assign:直接賦值(默認(rèn),適用于非OC對(duì)象) 3)copy:release舊對(duì)象,copy新對(duì)象② 控制成員變量屬性的參數(shù) 1)readwrite:同時(shí)生成setter和getter的聲明、實(shí)現(xiàn) 2)readonly:只會(huì)生成getter的聲明、實(shí)現(xiàn)③ 多線程管理相關(guān)參數(shù) 1)nonatomic:生成setter方法時(shí)不加線程管理代碼,性能高 (一般用這個(gè)) 2)atomic:生成setter方法時(shí)加上線程管理代碼,性能低(默認(rèn))④ 指定setter和getter名稱的參數(shù) 1)通過(guò)setter指定生成的set方法的名稱,通過(guò)getter指定生成的 get方法的名稱 2)不影響點(diǎn)語(yǔ)法的使用,點(diǎn)語(yǔ)法在使用時(shí)先轉(zhuǎn)換為對(duì)應(yīng)的set或get 方法 3)通常當(dāng)get方法的返回值為BOOL類型數(shù)據(jù)時(shí),對(duì)get方法使用, set方法幾乎不用
4> 循環(huán)包含與循環(huán)引用
循環(huán)包含
① 但兩個(gè)類的聲明文件循環(huán)包含時(shí),通常要在一個(gè)文件中用@class 聲明另一個(gè)類② 使用規(guī)范 1)在.h文件中用@class聲明類 2)在.m文件中用#import包含類的聲明文件
循環(huán)引用
① 當(dāng)兩個(gè)OC類循環(huán)引用時(shí),會(huì)產(chǎn)生內(nèi)存管理問(wèn)題② 解決方法 1)在一個(gè)類的聲明中,指定@property的內(nèi)存管理參數(shù)為retain 2)在另一個(gè)類的生命中,指定@property的內(nèi)存管理參數(shù)為release
三、autorelease
1> 基本使用
作用
① 將調(diào)用該方法的對(duì)象放進(jìn)自動(dòng)釋放池,當(dāng)池子銷毀時(shí),對(duì)池子內(nèi)所有 的對(duì)象執(zhí)行一次release操作② 通常在對(duì)象創(chuàng)建時(shí)調(diào)用,放回對(duì)象本身
自動(dòng)釋放池的創(chuàng)建方式
① 通過(guò)@autoreleasepool{}創(chuàng)建② 通過(guò)NSAutoreleasePool類創(chuàng)建
2> 使用注意
3> 常見(jiàn)應(yīng)用
快速創(chuàng)建一個(gè)自動(dòng)釋放池內(nèi)的對(duì)象
① 通常設(shè)計(jì)一個(gè)類方法,快速創(chuàng)建一個(gè)自動(dòng)釋放池內(nèi)的對(duì)象② 方法名通常以類名開(kāi)頭③ 創(chuàng)建時(shí)要使用self調(diào)用alloc、init與autorelease方法,不要使用類名
四、ARC
1> 基本使用
強(qiáng)指針與弱指針
① 強(qiáng)指針 1)通過(guò)__strong聲明的指針 2)所有的指針默認(rèn)都是強(qiáng)指針② 弱指針 1)通過(guò)__weak聲明的指針 2)當(dāng)弱指針指向的對(duì)象被釋放,弱指針將被清空
判斷準(zhǔn)則
只要沒(méi)有強(qiáng)指針指向?qū)ο螅瑢?duì)象就會(huì)被釋放
2> @property的strong和weak參數(shù)
3> 循環(huán)引用的解決方法
五、示例(多文件)
/* 1.創(chuàng)建一個(gè)Person類和一個(gè)Dog類,Person類與Dog類是相互用有關(guān)系 2.重寫(xiě)Person類與Dog類的dealloc方法 3.重寫(xiě)Person類的set方法,實(shí)現(xiàn)內(nèi)存管理代碼 4.自定義Person類構(gòu)造方法,用于快速創(chuàng)建一個(gè)自動(dòng)釋放池內(nèi)的Person對(duì)象 */ /*****main.m文件******/#import <Foundation/Foundation.h>//包含Person類的聲明文件#import "Person.h"//包含Dog類的聲明文件#import "Dog.h"int main(){ //創(chuàng)建自動(dòng)釋放池 @autoreleasepool { //創(chuàng)建Dog對(duì)象,并加入到自動(dòng)釋放池中 Dog *d = [[[Dog alloc] init] autorelease]; /*通過(guò)調(diào)用類方法快速創(chuàng)建一個(gè)Person類型的自動(dòng)釋放池對(duì)象 并用Dog初始化新創(chuàng)建的對(duì)象的成員變量*/ Person *p = [Person personWithDog:d]; //將指針清空 p = nil; } return 0;}/*****Person.h文件******/#import <Foundation/Foundation.h>//聲明Dog是一個(gè)類,Dog.h文件用#import指令@class Dog;@interface Person : NSObject/*通過(guò)@property生成dog屬性的getter和setter 并使用參數(shù)retain,Dog.h使用assign參數(shù)*/@property (nonatomic, retain) Dog *dog;/*自定義方法,快速創(chuàng)建一個(gè)Person類型的自動(dòng)釋放池對(duì)象,并用Dog初始化新創(chuàng)建的對(duì)象的成員變量*/+ (Person *)personWithDog:(Dog *)dog;@end/*****Person.m文件******/#import "Person.h"//使用@class聲明的類,在實(shí)現(xiàn)文件中要用#import指令包含該類的頭文件#import "Dog.h"@implementation Person+ (id)personWithDog:(Dog *)dog{ Person *p = [[[Person alloc] init] autorelease]; //將dog賦值給新創(chuàng)建對(duì)象的成員變量 p.dog = dog; return p;}//重寫(xiě)dealloc方法- (void)dealloc{ NSLog(@"Person對(duì)象被釋放"); //釋放person所擁有的屬性 [_dog release]; //調(diào)用父類的dealloc方法 [super dealloc];}@end/*****Dog.h文件******/#import <Foundation/Foundation.h>//包含Person.h頭文件,Person.h文件用@class指令#import "Person.h"@interface Dog : NSObject/*通過(guò)@property生成person屬性的getter和setter 并使用參數(shù)retain,Person.h使用retain參數(shù)*/@property (nonatomic, assign) Person *person;@end/*****Dog.m文件******/#import "Dog.h"@implementation Dog//重寫(xiě)dealloc方法- (void)dealloc{ NSLog(@"Dog對(duì)象被釋放"); //釋放Dog所擁有的屬性 [_person release]; //調(diào)用父類的dealloc方法 [super dealloc];}@end
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注