OC知識點大全(筆記)


·成員變量與屬性的區別:[email protected]@[email protected]��,成員變量用來存儲屬性的值

//NSObject 屬性Foundation框架下的一個類

//iOS 中的四個基本框架:Foundation、SystemConfiguration、UIKit、CFNetWork

//對象的生命周期:對象的生命周期從 alloc 開始,到delloc結束

//通過屬性調用setter方法給_name賦值


修飾屬性關鍵字:atomic/nonatomic/readwrite/readonly/ assign/retain/strong/weak/copy/

@property(nonatomic,copy,readwrite,setter=setName:,getter=name)NSString

atomic/nonatomic 原子操作和非原子操作 (原子操作能保證多線程安全)

readwrite/readonly 讀寫權限

setter 屬性的寫方法名

getter 屬性的讀取方法


assign:修飾基本數據類型 直接賦值 NSInteger CGFloat int float double char

weak:修飾對象類型和id類型 弱引用 引用計數不會加一,防止循環引用 隻能在ARC環境中使用

strong:修飾對象類型 強引用 引用計數會加一 在ARC裡代替retain的作用 隻能在ARC環境中使用

retain:修飾對象類型 強引用 舊對象引用計數減一,新對象引用計數加一,如下set方法

-(void)setName:(NSString *)name {

if(_name){

[_name release];

}

_name = [name retain];

}


用strong或者weak修飾的對象的retainCount為0時,屬性會被置為nil,不會造成野指針,不會引起崩潰,而用retain/assign 修飾的對象retainCount為0時,是不會進行任何操作的,如果再用屬性去調用該對象時,可能會有崩潰現象,野指針操作


·使用copy 或 MutableCopy的對象 必須遵循NSCopy、NSCoding協議或者MutableCopy協議

copy:對不可變對象copy是淺拷貝,對可變對象copy是深拷貝

mutableCopy:一定是深拷貝


析構方法中:要將強引用的對象類型的屬性和成員變量釋放掉,置為nil;使用assgin 和weak修飾的屬性,不用管,釋放對象時,先釋放本類中的屬性和成員變量,在釋放父類中的屬性和成員變量


·內存管理:基本數據類型的數據 內存在棧上,棧內存由系統去開辟和回收,對象類型的數據 內存在堆上,內存管理就是對對象的內存管理、對堆內存的管理(系統中有一個管理系統空閑空間的鏈表存放著空閑狀態的內存,申請內存時 系統會遍歷鏈表找到大於等於申請的內存的結點將該結點分配給發起申請的對象,並將該結點從存儲空閑內存空間的鏈表中移除;釋放一個對象時,對象占的內存回到空閑狀態系統又會將對象的堆結點存入鏈表中,等待下一次分配)OC中的內存管理原則:誰引用,誰管理


·引用計數:繼承NSObject的類都有一個引用計數器retainCount,用於記錄當前被幾個指針引用

·內存管理原則:對象通過引用計數來進行內存管理,引用計數記錄對象被幾個指針引用。引用計數為零時對象就會被銷毀。


采用 alloc、new、copy/MutableCopy(深拷貝)創建對象時,對象的retainCount會增加 1

對一個對象發送 retain、copy 消息,進行強引用時(淺拷貝),對象的retainCount會加 1


**iOS 中的內存管理方式:**ARC、MRC、自動釋放池

ARC 和 MRC中內存管理的機制,從本質上講是一樣的,隻是不需要我們自己手動編寫 retain/copy/mutableCopy/strong/, 也不用去寫release/autorelease

autorelease:延遲釋放,調用autorelease對象的retainCount 不會立刻減1,而是被添加到自動釋放池管理延遲釋放對象的數組,等待自動釋放池執行結束時才會真正的釋放 retainCount - 1


·類方法創建的對象不需要手動release,原因是在類方法中添加瞭autorelease。缺點:不知道對象什麼時候被釋放,可能造成提前釋放

+ (instancetype)personWithName:(NSString *)name {

Person *p = [[self alloc] init];

p.name = name;

return [p autorelease];

}


·向數組中添加對象時 對象的retainCount會加一,從數組中移出對象,對象的retainCount會減一

·向字典中添加鍵值對時 對象的retainCount會加一,從字典中移出對象,對象的retainCount會減一


//Block的用法,是OC中的一種語法

/**

1.block的聲明

2.block的實現和賦值

3.block的調用

4.block作為函數的參數

5.block作為函數的返回值

*/


// 如果回調隻有一種或兩種情況的時候,使用block進行回調比較方法,如果有多種回調情況的,采用協議代理
//1.聲明block的變量 : 返回值(^block變量名)(參數類型1 參數名,參數類型2 參數名); 聲明時,參數名可以省略,但是不推薦省略
//Swift中聲明閉包: var closure:((參數名:參數類型,參數名2:參數類型,...)->(返回值類型1,返回值類型2,...)) ={(參數名1,參數名2,...) in 閉包體 }

//使用block需要註意的問題:
//1.聲明block類型的屬性時,修飾的關鍵詞 copy
//2.block要避免閉環強引用
void(^blockName)(NSString * str,BOOL success);

// 省略參數的寫法:void(^blockName1)(NSString *,BOOL);


//2.block的實現和賦值
blockName = ^(NSString * str,BOOL success){
//block的實現部分,block體
//聲明和賦值時,block體中的代碼都不會執行
NSLog(@"執行blokc體中的代碼");
};
//3.調用block
blockName(@"bwrgrets",YES);
//4.block作為函數的參數
int(^useBlock)(NSString *) = ^(NSString * str){
NSLog(@"調用blokc str = %@",str);
return 0;
};

//調用函數
[self useAblock:useBlock];
[self useAblock:^int(NSString *str) {

// block 體

NSLog(@”哈哈哈”);

return 1;

}];


//5:block作為函數的返回值
void(^getBlock)() = [self returnABlock];
//調用返回的block
getBlock();

//采用self.myBlock 對block屬性賦值,myBlock聲明時內存相關的關鍵詞是 copy ,所有調用setter方法是,self對block實現部分進行瞭一次強引用


//解決閉環強引用:讓block對當前對象的引用變成弱引用,用一個當前類的弱引用類型指針pName指向self,在block體中使用pName去代替self
__weak NewViewController *pName = self;
__unsafe_unretained NewViewController * p = self;
//__weak 修飾,對象被釋放之後,pName會被置為nil,不會造成野指針,比較安全,隻能在ARC環境中使用
//__unsafe_unretained修飾,對象被釋放之後,p不會置為nil,會造成野指針,可能會造成程序崩潰,ARC/MRC環境中都能使用
self.myBlock = ^(NSString *str){
NSLog(@"什麼都不做");
NSLog(@"name = %@",pName.name);
//在blcok體中 使用的對象,都會被block 進行拷貝,一次強應用,我們調用瞭self.name,這是block對self進行一次強引用
};

————————

代理:

主動類(給別人東西的類):制定協議(協議構成:當前類的名字+delegate),生成id類型的屬性,調用協議方法 (註意:delegate的修飾詞是assign,目的是防止循環引用)

被動類(接收東西的類):遵守協議,將自己設置成主動類的代理類,實現協議方法

例題:用代理實現從配置界面回到主界面時,改變主界面中一個按鈕的大小為40號字體

思路:當兩個類之間有需求關系的時候,往往用到代理。先確定好主動類和被動類(主動類:關鍵是id的屬性和協議 被動類:聲明協議和實現協議),發出命令的一般是主動類,即主動類有需求;執行命令的一般是被動類




沙盒:應用程序的所在地

裡面共有三個文件夾

Documents:放到是用戶請求的到的數據和需要長期保存的數據

libaray:存放的程序的系統設置,默認設置等

tmp:存放的是臨時文件


·OC 中的拓展方法:類別、協議、延展、繼承

//用類別可以添加屬性,但是實現的時候要借助runtime 添加鍵值對和訪問權限(在類別中添加屬性,隻是聲明瞭setter 和 getter ,但是在類別的實現部分,系統並不會真正的去 實現這兩個方法)


.h文件

@property (nonatomic, copy) NSString * subject;

.m文件

-(void)setSubject:(NSString *)subject{

objc_setAssociatedObject(self, “subject”, subject, OBJC_ASSOCIATION_COPY_NONATOMIC);

//OBJC_ASSOCIATION_COPY_NONATOMIC 非原子操作,copy修飾屬性

}

-(NSString *)subject{

return objc_getAssociatedObject(self, “subject”);

}

//延展:選擇性公開在原類實現文件中聲明的成員變量、屬性、和方法


單例:

指的是某個類的對象,在整個程序運行期間,隻被創建一次,並且在整個程序運行期間都不會被銷毀

使用單例的優點:不用多次創建對象、整個工程都可以訪問這個對象的數據,實現數據共享

缺點:單例對象在程序運行期間都不會被銷毀,很多時候都占用內存,內存泄露問題(在工程中謹慎使用單例模式)


static Person * p = nil;


@implementation Person


//OC中最簡單的單例實現方式,但是並不推薦這樣去寫,多線程環境下,這樣是不能保證線程安全

+(instancetype)sharePerson{


if(!p){
p = [[self alloc]init];
}
return p;

}


+(instancetype)defaultPerson{

//使用關鍵字對對象加鎖,保證線程安全,這是蘋果推薦的單例實現方法之一

@synchronized (p) {

if(p == nil){

p = [[Person alloc]init];

}

}

return p;

}


+(instancetype)sharePerson1{

//采用GCD dispatch_once 保證創建對象的代碼在整個程序運行期間隻被執行一次

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

if(p == nil){

p = [[Person alloc]init];

}

});

return p;

}


//1.什麼是代理設計模式/簡述一下你對代理設計模式的認識

//2.使用代理設計模型應該註意什麼問題

//代理設計模式的三要素

/**

1.委托方:想要到達某種目的,而自身做不到,想要通過其他的對象幫助自己來完成操作;聲明delegate屬性

2.代理方:能完成某種特定功能的對象,但是這些方法,通常不由自己觸發,而是通過委托方調用觸發

3.協議:約定瞭委托方能夠調用的方法,以及代理方要失效的方法

*/


/**實現協議代理的步驟

1.首先明確委托方,有委托方根據自己要實現的功能,擬定協議方法

2.明確代理方:實現協議方法,接受委托方的委托

3.委托方和代理方建立代理關系 :委托方的delegate 屬性 指向 代理方來完成

4.委托方調用協議方法

5.代理方法執行協議方法

*/


@[email protected],要求代理對象必須實現

-(void)teach:(NSString *)subject;

@[email protected],代理方可以選實現

0 個評論

要回覆文章請先登錄註冊