OC基礎

Oc基礎

1、#import的用途

1>#import與#include一樣,拷貝文件的內容

2>可以自動防止文件的內容被重復拷貝

2、#import

? ? ? ? NSLog(<#NSString * _Nonnull format,…#>)聲明的函數(shù)

3、Foundation框架頭文件路徑

1>、Xcode右擊,顯示報內容

2>、/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks

4、主頭文件

1>、最主要的頭文件,名字一般跟框架名一樣,包含框架中所有的其他文件

2>、Foundation框架的主頭文件名稱就是Foundation.h

3>、只要包含了Foundation的主頭文件,就可以使用整個框架的東西

5、運行過程

1>編寫代碼? .m .c

2>編譯? xxx.m xxx.c

3>鏈接? xxx.o xxx.o

4>運行? ? ./a.out

6、在使用類的時候,會將類加載到內存中

沒有對象內部都有一個isa指針,這個指針指向類的方法列表

7、方法與函數(shù)的區(qū)別

方法:

1>對象方法以-號開頭

2>方法的聲明必須寫在@interface@end之間

?? ? ? 方法的實現(xiàn)必須寫在@implementationend之間

3>對象方法只能又對象來調用

4>對象方法歸對象和類擁有

函數(shù):

1>函數(shù)可以寫在文件的任意位置,函數(shù)歸文件所有

2>函數(shù)的調用不依賴于對象

8、匿名對象

就是創(chuàng)建對象的時候,沒有指針去指向這個對象

9、類方法和對象方法可以同名

類方法的執(zhí)行效率比較高,但是類方法不能訪問成員變量

10、工具類:基本沒有任何成員變量的時候,里面的方法都是類方法。

11、繼承

1>子類不能擁有和父類相同的成員變量

2>父類必須聲明在子類之前

3>調用某個對象的方法,優(yōu)先從該對象中查找,如果找不到再去父類中查找方法的實現(xiàn)

每個類中都有一個superClass指針,指向自己的父類,進而才可以去

super關鍵字的使用

1>super直接調用父類的方法

2>具體調用super的對象方法還是類方法,完全取決于當前的環(huán)境

3>子類中想先調用父類的方法之后,才去調用子類的方法時候,可以調用下super的方法

12、多態(tài):父類的指針指向子類的對象 (狗 是DOG類型 ,它的父類是animation。所以一個狗的對象既可以用狗類的對象指針指向,也可以用動物類對象的指針指向)

1>沒有繼承就沒有多態(tài)

2>如果函數(shù)的參數(shù)是父類,那么參數(shù)對象可以傳子類、父類對象

3>局限性:父類類型的變量不能直接調用子類類型特有的方法

13、成員變量的作用域

局部變量、全局變量有自己的作用域,成員變量也不例外。

成員變量的作用域:

@public:在任何地方都能訪問對象的成員變量? ? ? ? ? ? ?

@private:只有當前類的對象方法中訪問? ? 或者是用set/get方法 @implementation中聲明的成員變量默認是private

@protected:可以在當前類以及子類的對象中直接訪問(默認就是@protected)或者是用set/get方法

@package:只要處于同一框架,就可以直接訪問對象的成員變量

@implementation中也能定義一個成員屬性,但是默認是私有的

@interface@implementation不能聲明同名的成員屬性

14、@property? int age;會自動生成setAgeage方法的聲明

@synthesizeage = _age;會自動聲明setAgeage方法的實現(xiàn),而且這句話會訪問_age這個屬性,如果不存在就會自動幫我們創(chuàng)建一個@private_age屬性。

@synthesizeage(如果不寫=_age)會自動聲明setAgeage方法的實現(xiàn),而且這句話會訪問_age這個屬性,如果不存在就會自動幫我們創(chuàng)建一個@privateage屬性。

Xcode4.3之后@property? int age這一句代碼就會幫我們生成 _age 以及setAge、age的方法聲明與實現(xiàn),但是這個方法生成的成員屬性是私有的,不能讓子類進行訪問,如果想讓子類進行訪問,那么就需要在.h中聲明聲明一個protected_age屬性

如果手動實現(xiàn)了set方法,那么編譯器就只會生成get方法和下劃線屬性

如果手動實現(xiàn)了get方法,那么編譯器就只會生成set方法和下劃線屬性

如果手動生成了setget方法,那么編譯器就不會幫你生成下劃線屬性

15、構造方法

用來初始化對象的方法,是一個對象方法

重寫init方法:

1>調用【super init】方法初始化父類的屬性,并賦值給self

2>判斷self是否為空,不為空則進行初始化屬性操作

3>返回self

重寫構造方法的目的:為了創(chuàng)建對象的時候,成員變量就有值

-(instancetype)init{

? ? if(self=[superinit]){

? ? ? ? _age? =10;

? ? }

? ? returnself;

}

自定義構造方法:

1>一定是對象方法,以 - 開頭

2>返回類型是 id類型

3>方法名以initWith開頭

-(instancetype)initWithAge:(int)age{

? ? if(self=[superinit]){

? ? ? ? _age = age;

? ? }

? ? returnself;

}

16、修改Xcode創(chuàng)建文件的時候的一些配置屬性

/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates在這里面修改

17、分類:可以給某一類擴展一些方法,在不改變原來類的基礎上,為類增加一寫方法。

分類的使用注意:

1>只能增加方法,不能只能成員變量

2>分類方法的實現(xiàn)中可以訪問原來類的成員變量

3>分類可以重新實現(xiàn)原來類中的方法,但是會覆蓋掉原來類中的方法,會導致原來類中的方法無法使用

4>方法調用的優(yōu)先級: 分類(最后編譯的分類優(yōu)先) —> 原類 —> 父類

18、

1>當程序啟動時,就會加載項目中所有的類和分類,而且加載后會調用類和分類的+ (void)load{? ?

}方法,只會調用一次

2>當?shù)谝淮问褂媚硞€類的時候,會調用當前類的+(void)initialize

}方法

3>先加載父類,再加載子類,最后加載分類的(先調用父類的load方法,再調用子類的load方法)

先初始化父類,再初始化子類(先調用父類的initialize方法,再調用子類的initialize方法)

19、類也是個對象

類也是一個對象,是一個class類型的對象,簡稱類對象

Class類型的定義

typedefstructobjc_class * Class

類名就代表類對象,每個類只有一個對象

20、-(NSString *)description{}方法

默認情況下,利用NSLog和%@輸出對象的時候,結果是<類名:內存地址>

1>會調用對象的description方法

2>拿到description方法的返回值展示到屏幕上

3>description默認返回的是“類名+內存地址”

+(NSString *)description{}方法,類的-(NSString *)description{}方法,默認返回的是類名

21、? ? NSLog(@"%s",__FILE__);

NSLog輸出c語言字符串的時候,不可以包含中文

22、SEL

typedefstructobjc_selectorSEL

SEL s = NSSelectorFromString(@"test")

NSStringFromSelector(@selector(test))

_cmd代表當前方法

?NSString *s = NSStringFromSelector(_cmd);

SEL其實是對方法的一個包裝,去找到對應的方法地址就可以調用此方法

內存管理? ?

1、局部變量的對象是放在棧中的,系統(tǒng)會管理他們的內存

?? ? 一個oc對象的內存是放在堆中的,需要我們去手動管理他的內存

2、每個對象的內部都有四個字節(jié)來存儲對象的內存空間

當一個對象alloc /new /copy的時候引用計數(shù)器會+1

給對象發(fā)送 retain 消息的時候,對象的引用計數(shù)器+1

? ? ? ? 給對象發(fā)送release消息的時候,對象的引用計數(shù)器-1

? ? ? ? 給對象發(fā)送 retainCount 消息的時候,返回對象的引用計數(shù)器的個數(shù)

3、對象銷毀

?? ? ? 當一個對象的引用計數(shù)器為0的時候,系統(tǒng)會給對象發(fā)送一個dealloc消息,一般重寫此方法在其中做一些釋放性的操作

4、野指針: 指針指向了一塊已經(jīng)釋放的內存對象(這個對象成為僵尸對象)給野指針發(fā)送消息會報錯 野指針經(jīng)常報錯為 EXC_BAD_ADRESS

? ? ? 空指針:沒有指向任何對象的指針(存儲的為nil/NULL/0) oc中給nil 發(fā)送消息不會報錯

? ? ? 僵尸對象:所占用的內存已經(jīng)被回收的對象,僵尸對象不能再繼續(xù)使用

5、retain方法會返回對象本身

? ? ? release方法不會有返回值

6、delloc

? ? ? 當對象要被回收的時候會調用、一定要調用【super delloc】,因為【super delloc】中也要做一些釋放操作,而且這一句一定要寫在最后

7、alloc/new/mutableCopy來創(chuàng)建對象的時候,引用計數(shù)器會+1,不使用這個對象的時候,需要將引用計數(shù)器-1

8、誰retain了,誰就要release

9、當你想使用或者占有某個對象的時候,需要對對象進行一次retain操作

? ? ? 當你不想使用或者占有某個對象的時候,需要對對象進行一個release操作

? ? ? 誰retain誰release

? ? ? 誰alloc誰release

10、假如person? 有一個car屬性

_car:直接訪問成員屬性

self->_car:直接訪問成員屬性

self.car? :get方法

[self car]:get方法

11、MRC中的set方法?

@interfacePerson : NSObject

{

? ? Car *_car;

}

-(void)setCar:(Car *)car;

-(Car *)car;

@end

@implementationPerson

-(void)setCar:(Car *)car{

? ? if(_car != car){? ? ? ? //這個判斷是為了防止調用多次[self car]此時的car為同一個car,先給_car做一次release操作,此時car已經(jīng)被釋放了,然后再去調用【car retain】方法,這個相當于是給一個僵尸對象發(fā)送了一個retain消息。

? ? ? ? [_car release];? ? //這個是為了防止在你給對象賦值新的car的時候,原有的car沒有做release操作,而導致的原有的car不會被釋放

? ? ? ? _car =[car retain];//這段代碼是為了誰擁有誰就要去retain

? ? }

}

-(Car *)car{

? ? return_car;

}

@end

12、內存管理的原則

1>只要調用了alloc,就必須調用release或者autorelease

2>set方法的代碼規(guī)范

?? 基本數(shù)據(jù)類型:

-(void)setAge:(int)age{

_age = age;? 直接賦值

}

? ? 對象類型:

-(void)setCar:(Car*)car{

if(_car != car){

[_car release];//對舊對象進行release操作

_car =[car retain];//對新對象進行retain操作

}

}

3>delloc //對self所擁有的所有對象進行一次release操作

-(void)delloc{

[_car? release];

//最后調用【super delloc】

[super delloc];

}

13、property默認生成的set和get方法是直接賦值assign

14、property(retain)就是相當于在set方法中先release舊值,再retain新值

15、property的參數(shù)有四個

1>set方法內存管理的相關參數(shù)

*retain:先release舊值,再retain新值

*assign:直接賦值

*copy

2>多線程管理

nonatomic :(性能高,set方法的時候不加線程鎖)

atomic :(性能低,加線程鎖)

3>是否只生成set和get方法

*readwrite:同時生成set和get方法的聲明與實現(xiàn)

*readolny:只生成get的聲明與實現(xiàn)

4>set和get的方法名稱

setter:決定了set:的方法名,一般是需要帶冒號的

getter:決定了getter方法名(一般用在bool類型)

例如:

@property(nonatomic,retain,readwrite,setter=setCarrrrr:,getter=carrrrr)Car *car;

16、

定義一個枚舉

typedefenum{

? ? SexMan,

? ? SexWoman

} Sex;

定義一個結構體

typedefstruct{

? ? intyear;

? ? intmonth;

? ? intday;

} Date;

17、@class只是告訴對象 這是一個類 , 但是不包含.h中的屬性與方法

?1>@class只是告訴編譯器某個名稱是一個類,例如@class person僅僅告訴編譯器person是一個類

2>開發(fā)中引用一個類的規(guī)范

在.h中用@class來聲明

在.m中用import來包含類的聲明

3>兩端循環(huán)引用的解決方案

一端用retain一端用assign

在.h中用@class來聲明可以解決循環(huán)包含的錯誤?

例如

#import <Foundation/Foundation.h>

#import "Person.h"

@interfaceCar : NSObject

@property(nonatomic,retain)Person *p;

@end

#import <Foundation/Foundation.h>

#import "Car.h"

@interfacePerson : NSObject

@property(nonatomic,retain)Car *car;

@end

這樣會報錯,編譯不通過

#import <Foundation/Foundation.h>

@classPerson;

@interfaceCar : NSObject

@property(nonatomic,retain)Person *p;

@end

#import <Foundation/Foundation.h>

@classCar;

@interfacePerson : NSObject

@property(nonatomic,retain)Car *car;

@end

這樣才不會報錯,編譯可以通過,然后在.m文件中用#import “”來包含頭文件

這樣做編譯效率也比較高,如果按照第一種方式,一旦包含的類種的屬性或者方法修改過了,就會造成每一個只要#import “”的.h都會重新編譯一遍,造成效率比較低

18、autorelease的使用

autorelease方法會返回對象本身

autorelease 會把對象放在一個自動釋放池中,當自動釋放池被銷毀的時候,會對池中的對象做一次release操作

? ? @autoreleasepool{

? ? ? ? Person *p =? [[[Person alloc]init]autorelease];

? ? }

會在池子結束的時候,對person對象調用一次release操作

autoreleasepool是可以嵌套使用的,而且autoreleasepool是放在棧內存中的,先進后出。

autoreleasepool的基本用法:

1>會將對象放入一個自動釋放池中

2>當自動釋放池銷毀的時候,會對池中的對象進行一次release操作

3>會返回對象本身

4>調用完autorelease方法,對象的引用計數(shù)器不變,只有當autoreleasepool執(zhí)行完畢之后,才會對池中的所有對象進行一次release操作

autorelease的好用:

1>不用關心對象釋放的時間

2>不用關心什么調用對象的release

autorelease的使用注意:

1>占用較大內存的對象,不要隨便的使用autorelease

2>占用較小內存的對象使用autorelease沒有太大的影響

池子autoreleasepool的錯誤寫法:

1>? ? @autoreleasepool{

? ? ? ? Person *p =? [[[[Person alloc]init]autorelease]autorelease];//調用兩次autorelease會出現(xiàn)野指針錯誤

? ? }

2>? ? @autoreleasepool{

? ? ? ? Person *p =? [[[Person alloc]init]autorelease];

? ? ? ? [p release];

? ? }? ? ? ? 也會出現(xiàn)也指針錯誤

3>? ? ? ? Person *p =? [[[Person alloc]init]autorelease];這樣寫沒有任何的意義,因為autorelease不放到autoreleasepool中是不會調用release

自動釋放池:

1>ios程序中也會創(chuàng)建自動釋放池,這些自動釋放池以棧的形式存在

2>當一個對象調用autorelease方法的時候,會將這個對象放到棧頂?shù)尼尫懦?/p>

自動釋放池的創(chuàng)建方法:

#pragma mark ios5之前

? ? NSAutoreleasePool *pool =[[NSAutoreleasePool alloc]init];

? ? Person *p =? [[[Person alloc]init]autorelease];

? ? [pool release];

#pragma mark ios5之后

? ? @autoreleasepool{

? ? ? ? Person *p =? [[[Person alloc]init]autorelease];

? ? ? ? [p release];

? ? }

}

19、

1>系統(tǒng)自帶的方法沒有alloc/new/copy,說明返回的對象都是autorelease的

例如? NSString *str =[NSString stringWithFormat:@"string"];

? ? NSString *str1 =[NSString stringWithString:@"string"];

2>開發(fā)中經(jīng)常提供一些類方法快速創(chuàng)建一個已經(jīng)autorelease的對象

創(chuàng)建對象的時候,不要直接用類名,要用self,以滿足子類的需求

例如

+(id)person{

? ? return? [[[selfalloc]init]autorelease];

}

內存管理的總結:

一、計數(shù)器操作:

1>retain +1;

2>release -1;

3>retaincount? :獲取計數(shù)器

二、set方法的內存管理

1>set的實現(xiàn)

-(void)setCar:(Car *)car{

? ? if(_car != car){

? ? ? ? [_car release];

? ? ? ? _car =[car retain];

? ? }

}

2>delloc方法的實現(xiàn)(不要直接調用delloc)

-(void)dealloc{

? ? [_car dealloc];

? ? [superdealloc];

}

三、property參數(shù)

oc對象:

@property(nonatomic,retain)類名*屬性名;

非oc對象:

@property(nonatomic,assign)類型名稱屬性名;

四、@autoreleasepool

1、系統(tǒng)的方法中如果不帶有alloc、new、copy,這些方法返回的對象都是已經(jīng)autorelease過的

2、在開發(fā)過程中用類方法創(chuàng)建對象的時候,不要直接使用類名。可以用self(利用類方法快速創(chuàng)建一個autorelease對象)

ARC

ARC的判斷準則:只要沒有強指針指向對象,就會釋放對象

1>ARC的特點是不允許調用retain/release/retainCount

2>允許重寫delloc,但是不允許調用【super delloc】

3>property參數(shù)

*strong 成員變量是強指針 ,相當于之前retain(只適用于oc對象)

*weak成員變量是弱指針,相當于之前的assign(適用于oc對象)

*assign:適用于非oc對象

指針分為兩種:

強指針:__strong 默認情況下就是強指針

弱指針:__weak? 當弱指針指向的對象消失后,默認會指向nil

ARCMRC的轉換

1>mrc項目 arc

xcode -> edit ->convert -> to object ARC

2>查看項目當前是否為 ARC

buildSetting ->搜索auto -> objectc automatic reference counting ->yes代表arc No代表mrc

3>將項目中某個文件改為 arc或者mrc

build phases ->compile source ->-fno-objc-arc不需要arc或者-f-objc-arc需要ARC

當兩端循環(huán)引用的時候,解決的方案

1、ARC

一端用strong一端用weak

2、非arc

一端用retain一端用assign

Block:

intsum(inta,intb){

? ? returna+b;

}

-(void)viewDidLoad {

? ? [superviewDidLoad];

? ? int(*p)(int,int)= sum;

? ? intsum = p(10,12);

? ? NSLog(@"%d",sum);

}

指向函數(shù)的指針

int(^sumBlock)(int,int)=^(inta,intb){

? ? ? ? returna+b;

? ? };

? ? sumBlock(100,100);

1>如何定義block變量

Int(^SumBlock)(int,int);

void(^myBlock)();

2>如何利用block封裝代碼塊

^(int a,int b){

return a-b

};

^(){

NSLog(@“111111”);

};

3>block訪問外部變量

*block內部可以訪問外面的變量

*默認情況下,block內部不能修改外面的變量

*給局部變量上加上__block關鍵字,這個局部變量才可以在block內部修改

4>利用typedef定義block類型

typedefint(^MyBlock)(int,int);

以后就可以利用MyBlock這種類型來定義block變量

協(xié)議Protocol

1>基本用途

*可以用來聲明一大堆方法

*只要某各類遵守了這個協(xié)議,就相當于擁有了這個協(xié)議的所有方法

*只要父類遵守了某個協(xié)議,就相當于子類也遵守了

2>格式

@protocol協(xié)議名稱

//協(xié)議方法

@end

某個類遵守某個協(xié)議

@interface類名:父類<協(xié)議名稱1,協(xié)議名稱2>

@end

3>關鍵字

@required:這個方法是必須實現(xiàn)的(若不實現(xiàn),編譯器會發(fā)出警告)

@optional這個方法不一定實現(xiàn)

4>協(xié)議遵守協(xié)議

*一個協(xié)議可以遵守其他多個協(xié)議,多個協(xié)議之間用逗號隔開

*一個協(xié)議遵守了其他協(xié)議,就相當于擁有了其他以協(xié)議中的方法聲明

@protocol協(xié)議名稱<協(xié)議1,協(xié)議2>

@end

5>基協(xié)議

*nsobject是一個基類,最根本最基礎的類,熱河其他類都要繼承它

*其實還有一個協(xié)議,名字也叫NSobject,它是一個基協(xié)議,最根本的協(xié)議

*nsobject協(xié)議中聲明很多最基本的方法,比如description、retain、release等

*建議每一個新協(xié)議都要遵守nsobject協(xié)議

6>定義一個變量的時候,限制這個變量保存的對象遵守某個協(xié)議

類名<協(xié)議名稱>*變量名;

id<協(xié)議名稱>變量名;

NSObject*object;

Idobj2;

如果沒有遵守協(xié)議,編譯器會報警

7>@propety中聲明的屬性也可以用作一個遵守協(xié)議的限制

@property(nonatoimic,strong)類名<協(xié)議名稱>*屬性名

8>協(xié)議可以定義在單獨的.h中,也可以定義在某個類型中

*如果這個協(xié)議只用在某個類中,應該定義在該類中

*如果某個協(xié)議用在很多類中,就應該把協(xié)議定義在單獨的文件中

9>分類可以定義在單獨.h和.m文件中,也可以定義在原類中

1>一般情況下,都是定義在單獨文件

2>定義在原類中的分類,只要求看懂語法

集合中的對象的內存管理

1>當對象被添加到集合中的時候,對象的引用計數(shù)器會加一

2>當集合被銷毀的時候,會對集合中的對象發(fā)送一次release消息

3>當對象被移除的時候,也會給對象發(fā)送一次release消息

@property內存管理的策略

1非ARC

1>copy:只用于nsstring/block

2>retain:除nsstring/block以外的oc對象

3>assign:基本數(shù)據(jù)類型、枚舉、結構體(非oc對象)當兩個對象相互引用的時候,一端用retain一端用assign

2ARC

1>copy:只用于nsstring/block

2>strong:除nsstring/block以外的oc對象

3>assign:基本數(shù)據(jù)類型、枚舉、結構體(非oc對象)

4>weak當兩個對象相互引用的時候,一端用retain一端用assign

自定義類實現(xiàn)copy操作

1>類遵守NSCopying協(xié)議

2>實現(xiàn)-(id)copyWithZone:(nullableNSZone *)zone;方法

3>在- (id)copyWithZone:(nullableNSZone *)zone方法中創(chuàng)建一個新的對象,并設置該對象數(shù)據(jù)與現(xiàn)有對象一致,并返回該對象

單例模式

alloc方法其實調用的是allocWithZone

Static修飾局部變量,只創(chuàng)建一次

static修飾的全局變量,只有當前文件才可以訪問,并且只創(chuàng)建一次

1>永遠只分配一塊內存來創(chuàng)建對象

2>提供一個類方法,返回內部唯一的一個對象

3>最好保證init方法也只初始化一次

Dispath_once方法是線程枷鎖的,能保證線程安全

非ARC單例模式的實現(xiàn)比ARC單例模式的實現(xiàn)多了

-(id)retain{

}

-(NSUInteger)retainCount{

}

-(onewayvoid)release{


}

-(instancetype)autorelease{


}

// ## : 連接字符串和參數(shù)

#if __has_feature(objc_arc)判斷編譯環(huán)境是ARC還是MRC

#define singleton_h(name)+(instancetype)shared##name;

#if __has_feature(objc_arc)// ARC?

#define singleton_m(name)\

static id _instance;\

+(id)allocWithZone:(struct _NSZone *)zone \

{ \

? ? static dispatch_once_t onceToken;\

? ? dispatch_once(&onceToken,^{ \ dispatch_once線程安全,枷鎖了

? ? ? ? _instance =[super allocWithZone:zone];\

? ? });\

? ? return _instance;\

} \

?\

+(instancetype)shared##name \

{ \

? ? static dispatch_once_t onceToken;\

? ? dispatch_once(&onceToken,^{ \

? ? ? ? _instance =[[self alloc]init];\

? ? });\

? ? return _instance;\

} \

+(id)copyWithZone:(struct _NSZone *)zone \

{ \

? ? return _instance;\

}

#else// ARC

#define singleton_m(name)\

static id _instance;\

+(id)allocWithZone:(struct _NSZone *)zone \

{ \

static dispatch_once_t onceToken;\

dispatch_once(&onceToken,^{ \

_instance =[super allocWithZone:zone];\

});\

return _instance;\

} \

\

+(instancetype)shared##name \

{ \

static dispatch_once_t onceToken;\

dispatch_once(&onceToken,^{ \

_instance =[[self alloc]init];\

});\

return _instance;\

} \

\

-(oneway void)release \

{ \

\

} \

\

-(id)autorelease \

{ \

return _instance;\

} \

\

-(id)retain \

{ \

return _instance;\

} \

\

-(NSUInteger)retainCount \

{ \

return 1;\

} \

\

+(id)copyWithZone:(struct _NSZone *)zone \

{ \

return _instance;\

}

#endif

控制器的生命周期

-(void)loadView{

? ? [superloadView];

}

-(void)viewDidLoad{

? ? [superviewDidLoad];

}

-(void)viewWillAppear:(BOOL)animated{

? ? [superviewWillAppear:animated];

}

-(void)viewDidAppear:(BOOL)animated{

? ? [superviewDidAppear:animated];

}

-(void)viewWillDisappear:(BOOL)animated{

? ? [superviewWillDisappear:animated];

}

-(void)viewDidDisappear:(BOOL)animated{

? ? [superviewDidDisappear:animated];

}

-(void)viewWillUnload{

? ? [superviewWillUnload];

}

銷毀view

-(void)viewDidUnload{

? ? [superviewDidUnload];

}

-(void)didReceiveMemoryWarning{

? ? [superdidReceiveMemoryWarning];

}

Block可以使用在定義之前聲明的局部變量

? ? inti=10;

? ? void(^myBlock)(void)= ^(){

? ? ? ? NSLog(@"%d",i);

? ? };

? ? i = 100;

? ? myBlock();

打印的結果是 10;

1>在定義block的時候,會在block中建立當前局部變量的內容的副本(拷貝)

2>后續(xù)對該值進行修改不會影響block中的數(shù)值

3>如果需要在block中保持局部變量的數(shù)值變化,需要使用————block關鍵字

4>使用————block關鍵字之后,同樣可以在block中修改變量的值

runtime

運行時機制:比較高級的特性,純C語言

平時的oc代碼——>C語言的運行時代碼

默認情況下任何block的內存都是分配在棧中的,隨時可能被回收。

對block進行一次copy操作就會把內存分配到堆中。

block會對代碼塊中的對象進行一次強引用,例如

self.block = ^{

self.age = 20;

}

這個時候,block會對self進行一次強引用,而block又是self的一個copy屬性,也屬于強引用,所以造成了循環(huán)引用;

因此當block中使用了對象的時候,需要判斷是否造成了循環(huán)引用。如果造成了循環(huán)引用,就需要用——weak 來重新用指針指向對象

或者__unsafe_unretained? 來重新修飾?

例如

__unsafe_unretainedPerson *p2 = p1;

? ? __weakPerson *p3 = p1;

? ? __weaktypeof(self)weakSelf =self;

? ? typeof(self) 就是用來判斷類型,即等價于 self的類型*

KVC

利用kvc可以隨意的修改一個對象的屬性或者成員變量(并且私有的也可以)

Person *p1 =[[Person alloc]init];

? ? Dog *dog =[[Dog alloc]init];

? ? [p1.dog setValue:@"dogname" forKey:@"name"];

? ? [p1.dog setValue:@"dogname" forKeyPath:@"dog.name"];

人對象有一個狗的屬性,狗又有name的屬性;

? ? [p1.dog setValue:@"dogname" forKey:@"name”];中的key只能是屬性名,否則會報錯;

? ? [p1.dog setValue:@"dogname" forKeyPath:@"dog.name"];

可以是路徑,又可以是屬性名

forKeyPath包含了for的功能,以后用forkeyPath

iOS中的多線程

1>一個NSTread對象就代表一條線程

2>創(chuàng)建和啟動線程

NSThread *thread =[[NSThread alloc]initWithTarget:selfselector:@selector(run:)object:@"hah"];

? [thread start];

3>主線程相關的用法

[NSThread mainThread];

[NSThread isMainThread];

?[thread isMainThread];

4>設置線程的優(yōu)先級

? ? [NSThread threadPriority];查看當前線程的優(yōu)先級

? ? [NSThread setThreadPriority:0.5];設置當前線程的優(yōu)先級

5>設置線程的名字

? ? thread.name = @"線程一";

6>創(chuàng)建線程的時候就啟動線程

?[NSThread detachNewThreadWithBlock:^{


? ? }];

? ? [NSThread detachNewThreadSelector:@selector(run:)toTarget:selfwithObject:@"哈哈"];

7>隱shi創(chuàng)建

? ? [selfperformSelectorInBackground:@selector(run:)withObject:@"哈哈”];

線程的狀態(tài)

當線程在阻塞和死亡狀態(tài)的時候,會退出可調度線程池中。但是內存還在。

線程狀態(tài)的控制

最后的參數(shù)是說這個performSelector方法是否等待執(zhí)行完畢,才繼續(xù)跳出子線程操作

GCD

會自動幫我們創(chuàng)建線程

MRC中隊列是需要釋放的? 當調用creat方法的時候,要調用dispatch_release(queue)方法去釋放隊列

在ios中凡是函數(shù)帶有create、copy/new/retain等字眼,都需要在不需要使用這個數(shù)據(jù)的時候調用release操作

?CFArrayRef array = CFArrayCreate(0,0,11,0);

? ? CFRelease(array);在調用CF函數(shù)的時候,即使是在arc環(huán)境下也需要調用一下release操作

CF(core Facation)框架在ARC中也需要手動release

同步函數(shù):

*串行隊列:不開啟新的線程,任務串行執(zhí)行

*串行隊列(主隊列)會出現(xiàn)死鎖

*并行隊列:不開啟新線程,任務串行執(zhí)行

異步函數(shù):

*串行隊列 :開啟一條新的線程,任務并行執(zhí)行

*串行隊列(主隊列)不會開啟新的線程

*并行隊列: 開啟新的線程,任務并行執(zhí)行

? ? dispatch_queue_t mainqueue = dispatch_get_main_queue();

? ? dispatch_sync(mainqueue,^{

? ? ? ? NSLog(@"這樣會死鎖");

? ? });

dispatch_queue_t mainqueue = dispatch_get_main_queue();

? ? dispatch_async(mainqueue,^{

? ? ? ? NSLog(@"這樣不會發(fā)生死鎖");

? ? });

因為異步函數(shù)雖然也是放在了主線程中,但是比較特殊,會將block中的代碼緩后執(zhí)行,所以不會出現(xiàn)死鎖

延遲執(zhí)行:

第一GCD:

?//全局并發(fā)隊列

? ? dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

? ? //計算執(zhí)行任務的時間

? ? dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW,(int64_t)(3.0 * NSEC_PER_SEC));

? ? //when的這個時間點去執(zhí)行queue的任務

? ? dispatch_after(when,queue,^{


? ? });

第二:

? ? [selfperformSelector:@selector(run:)withObject:@"hahha" afterDelay:3.0];

一次性代碼

?staticdispatch_once_t onceToken;

? ? dispatch_once(&onceToken,^{


? ? });

#define global_queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)

#define main_queue dispatch_get_main_queue()

?dispatch_group_t group = dispatch_group_create();

? ? dispatch_group_async(group,global_queue,^{

? ? ? ? //下載圖片1

? ? });

? ? dispatch_group_async(group,global_queue,^{

? ? ? ? //下載圖片2

? ? });

? ? dispatch_group_notify(group,main_queue,^{

? ? ? ? //當任務一 任務二 完成之后,回到主線程中去操作

? ? });


NSOpertion:

多線程

1.NSThread

1> 開線程的幾種方式

* 先創(chuàng)建,后啟動

NSThread *thread =[[NSThread alloc]initWithTarget:selfselector:@selector(run)object:nil];

[thread start];

* 直接啟動

[NSThread detachNewThreadSelector:@selector(run)toTarget:selfwithObject:nil];

[selfperformSelectorInBackground:@selector(run)withObject:nil];

2> 其他用法

NSThread *current =[NSThread currentThread];

+(NSThread *)mainThread;// 獲得主線程

3> 線程間通信

performSelectorOnMainThread.....

2.GCD(重點)

1> 隊列的類型

* 并發(fā)隊列

獲得全局的并發(fā)隊列: dispatch_get_global_queue

* 串行隊列

a.自己創(chuàng)建

dispatch_queue_create

b.主隊列

dispatch_get_main_queue

2> 執(zhí)行任務的方法類型

*同步(sync)執(zhí)行

*異步(async)執(zhí)行

3> 了解隊列和方法的配合使用

4> 線程間通信

dispatch_async(

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{

?? // 執(zhí)行耗時的異步操作...

?? dispatch_async(dispatch_get_main_queue(),^{

?? ? ? // 回到主線程,執(zhí)行UI刷新操作

?? });

});

5> 其他用法

dispatch_once

dispatch_after

dispatch_group_async\dispatch_group_notify

3.NSOperation

1> 基本使用

NSInvocationOperation

NSBlockOperation

2> NSOperationQueue(重點)

* 最大并發(fā)數(shù)設置

-(void)setMaxConcurrentOperationCount:(NSInteger)cnt;

* 設置依賴(面試題)

[operationB addDependency:operationA];// 操作B依賴于操作A

3>自定義Operation(了解基本流程)

4> 如何解決一張圖片(一個url)重復下載的問題(面試題)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • OC基礎總結 重新回過頭看這些基礎知識,對許多知識點都有新的認識,擁有堅實的基礎才能更快的成長。 OC內存管理 -...
    xx_cc閱讀 2,891評論 1 21
  • 1.ios高性能編程 (1).內層 最小的內層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結構(3).初始化時...
    歐辰_OSR閱讀 30,217評論 8 265
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,632評論 1 32
  • OC語言基礎 1.類與對象 類方法 OC的類方法只有2種:靜態(tài)方法和實例方法兩種 在OC中,只要方法聲明在@int...
    奇異果好補閱讀 4,517評論 0 11
  • 林深時不一定見鹿 海藍時不一定遇鯨 但夢醒時 我一定想見你
    姀蕭閱讀 236評論 0 6

友情鏈接更多精彩內容