1,為什么說(shuō)Object-C 是一門動(dòng)態(tài)語(yǔ)言?
主要設(shè)計(jì)兩個(gè)概念: 運(yùn)行時(shí)與多態(tài),即:對(duì)象類型,以及調(diào)用對(duì)象方法是在運(yùn)行時(shí)決定;可以從三個(gè)方面描述,如下:
-
動(dòng)態(tài)類型
對(duì)象類型的確定是在運(yùn)行期間,
如:
id類型,可以賦不同類型的對(duì)象,在運(yùn)行時(shí)決定具體類型;如:
NSData *test = [[NSString alloc] init],編譯時(shí)為NSData類型,運(yùn)行時(shí)為NSString類型;如:父類指針指向子類對(duì)象,編譯時(shí)為類型為父類,運(yùn)行時(shí)為具體子類(簡(jiǎn)單工廠模式)
-
動(dòng)態(tài)綁定
在運(yùn)行時(shí)決定方法的調(diào)用,用于消息發(fā)送機(jī)制,向某個(gè)對(duì)象傳遞消息,就會(huì)使用動(dòng)態(tài)綁定機(jī)制來(lái)決定需要調(diào)用的方法;
objc_msgSend會(huì)根據(jù)接收者與選擇子的類型,在接收者內(nèi)搜索方法列表,如果找到就響應(yīng),本類找不到就沿著繼承向上找,最后沒有響應(yīng)會(huì)執(zhí)行消息轉(zhuǎn)發(fā)機(jī)制;如:多態(tài)中的子類重寫父類方法,在運(yùn)行時(shí)確定確定調(diào)用方法;
如:在
.h文件聲明方法,在.m不實(shí)現(xiàn)方法,讓外界調(diào)用,編譯時(shí)不報(bào)錯(cuò),運(yùn)行時(shí)報(bào)錯(cuò); -
動(dòng)態(tài)加載
程序在運(yùn)行時(shí)根據(jù)需要在加載可執(zhí)行的代碼和資源;
如:利用
runtime動(dòng)態(tài)添加屬性,添加方法,替換方法;如:不同機(jī)型適配,
@2x,@3x資源的加載;
2,說(shuō)說(shuō)Object-C內(nèi)存管理
OC內(nèi)存管理分為MRC(手動(dòng)引用計(jì)數(shù)),ARC(自動(dòng)引用計(jì)數(shù)),遵循誰(shuí)創(chuàng)建,誰(shuí)釋放,誰(shuí)retain誰(shuí)release原則;
-
MRC
需要程序員自己管理內(nèi)存,使用alloc, copy, retain 使引用計(jì)數(shù)加一,對(duì)應(yīng)的要使用release引用計(jì)數(shù)減一,或者autorealease 標(biāo)記釋放;
-
ARC
由系統(tǒng)自動(dòng)管理內(nèi)存,在合適的時(shí)間釋放已經(jīng)失去作用的內(nèi)存空間.
-
引用計(jì)數(shù)
引用計(jì)數(shù)就是管理對(duì)象生命周期的的方式,當(dāng)我們創(chuàng)建一個(gè)新對(duì)象的時(shí)候,它的引用計(jì)數(shù)為1,當(dāng)有一個(gè)新的指針指向這個(gè)對(duì)象時(shí),其引用計(jì)數(shù)加一,當(dāng)某個(gè)指針不指向這個(gè)對(duì)象的時(shí)候,其引用計(jì)數(shù)減一,當(dāng)對(duì)象的引用計(jì)數(shù)變?yōu)?時(shí),說(shuō)明對(duì)象不再被任何指針指向了,這時(shí)候就可以將對(duì)象銷毀,回收內(nèi)存;
3,屬性的實(shí)質(zhì)是什么?包括哪幾個(gè)部分?屬性默認(rèn)的關(guān)鍵字有哪些?@dynamic關(guān)鍵字和@synthesize關(guān)鍵字是
做什么的?
-
屬性的本質(zhì)
屬性的本質(zhì)就是: 成員變量+存取方法 即:
ivar+setter+getter -
屬性關(guān)鍵字
strong、assgin、weak、unsafe_unretaind、nonatomic、atomic,readwrite,readonly,等等,各自作用不一一贅述
注意:循環(huán)引用中常使用weak解決,IBOutlet使用weak,因?yàn)楦缚臻g在可視化操作時(shí)已經(jīng)強(qiáng)引用了
assign可用于非OC對(duì)象,而weak必須用于OC對(duì)象,并且對(duì)象銷毀時(shí),會(huì)自動(dòng)置為nil -
@dynamic與@synthesize
使用@dynamic關(guān)鍵字,需要手動(dòng)添加getter、setter方法,@synthesize自動(dòng)生成setter、getter方法
4,說(shuō)說(shuō)代理,Block,通知
-
delegate
1,一對(duì)一的通訊交互,防止循環(huán)引用, 用
weak,釋放自動(dòng)置為nil.2,需要
@protocol定義協(xié)議方法,指定代理,代理對(duì)象需要實(shí)現(xiàn)協(xié)議方法.3,更注重過(guò)程,類似
tableView的代理方法,需要設(shè)置行數(shù),設(shè)置cell等,通訊較多推薦delegate -
Block(閉包)
1,一對(duì)一的通訊交互,防止循環(huán)引用,用
copy, 棧區(qū)拷貝到堆區(qū).2,寫法簡(jiǎn)潔,注重結(jié)果,如尾隨閉包,回調(diào)結(jié)果,適用于通訊單一.
3,__block作用:將外部變量的傳遞形式由值傳遞,變?yōu)橹羔槀鬟f,從而可以獲取并修改外部變量的值
-
NotificationCenter
1,一對(duì)多的通訊,通訊對(duì)象之間不需要建立關(guān)系,發(fā)送通知,注冊(cè)通知,接收通知后,注意移除通知;
2,代碼可讀性差.
5,可變集合類 和 不可變集合類的 copy 和 mutablecopy有什么區(qū)別
copy返回的都是不可變對(duì)象(調(diào)用可變對(duì)象方法會(huì)crash),mutableCopy返回的是可變對(duì)象只有對(duì)不可變的對(duì)象進(jìn)行
copy,是淺拷貝,其他情況都是深拷貝
-
淺拷貝
淺拷貝是指針拷貝,不生成新的指針地址
-
深拷貝
深拷貝是內(nèi)容拷貝,開辟新內(nèi)存,會(huì)生成行的指針地址,修改拷貝對(duì)象對(duì)原對(duì)象沒有影響
-
copy 與 mutablecopy
不可變集合類(
NSArray) 進(jìn)行copy是淺拷貝,指針復(fù)制, 進(jìn)行mutableCopy是深拷貝可變集合類(
NSMutableArray) 進(jìn)行copy,mutableCopy都是深拷貝
6,如何使自己寫的對(duì)象具有拷貝功能
遵守
NSCopying,NSMutableCopying協(xié)議-
實(shí)現(xiàn)協(xié)議方法
- (id)copyWithZone:(NSZone *)zone- (id)mutableCopyWithZone:(nullable NSZone *)zone
7,Category,Extension,繼承的作用,區(qū)別
- Category
不需要?jiǎng)?chuàng)建子類就能為現(xiàn)有類(系統(tǒng)類,自定義類)添加新方法;
-
作用
1,可以將類的實(shí)現(xiàn)分散到多個(gè)不同的文件中.
2,創(chuàng)建對(duì)私有方法的向前引用(類別中的聲明方法未實(shí)現(xiàn),編譯器不會(huì)產(chǎn)生警告)
3,向?qū)ο筇砑臃钦絽f(xié)議
-
局限
1,類別中只能添加方法,不能添加屬性,(可以通過(guò)runtime添加)
2,方法名沖突,類別中方法名,與原始類方法名相同時(shí),類別具有更高的優(yōu)先級(jí),先調(diào)用類別方法,覆蓋原始類方法
- Extension
extension是延展,匿名分類,一般用于聲明私有屬性,成員變量,私有方法.
-
與
Category的區(qū)別1,
extension可以添加屬性,而Categary不可以添加屬性(可以通過(guò)runtime添加)2,
extension不能單獨(dú)存在,必須寄生于類的.m中,即:需要源碼,而categary可以單獨(dú)存在,不需要源碼.3,
extension在編譯器決議,它是類的一部分,而categary,是在運(yùn)行期決議. 繼承
繼承是面向?qū)ο笳Z(yǔ)言的特性,子類可以繼承父類的屬性與方法,如
BaseController
-
使用條件
1,當(dāng)需要擴(kuò)展的方法與原方法同名時(shí),并且需要調(diào)用父類的同名方法,則需要繼承。若此時(shí)使用分類,則分類的方法的實(shí)現(xiàn) 會(huì)覆蓋原方法的實(shí)現(xiàn),不會(huì)訪問到原方法。
2,當(dāng)需要擴(kuò)展屬性時(shí)。
8,Object-C的反射機(jī)制
OC的反射機(jī)制分為
Class反射和SEL反射
-
class反射
通過(guò)類名字符串獲取類
Student *stu = [[NSClassFromString(@"Student") alloc]init]將類名,轉(zhuǎn)化成字符串
NSString *stuString = NSStringFromClass([Student class]) -
SEL反射
通過(guò)方法字符串,實(shí)例化方法
[stu performSelector:NSSelectorFromString(@"setName") withObject:nil]將方法變成字符串
NSStringFromSelector(@selector*(setName:))
9,常見的系統(tǒng)單利類有哪些?如何實(shí)現(xiàn)完整的單利?
-
系統(tǒng)單利類
1,應(yīng)用程序?qū)嵗?[UIApplication sharedApplication]
2,消息中心 [NSNotificationCenter defaultCenter]
3,文件管理 [NSFileManager defaultManager]
4,應(yīng)用程序設(shè)置 [NSUserDefaults standardUserDefaults]
5,應(yīng)用程序cookies池 [NSHTTPCookieStorage sharedHTTPCookieStorage]
-
完整的單利類
實(shí)現(xiàn)了單例的初始化之后,一定要重寫三個(gè)方法
+(id) allocWithZone:(struct _NSZone *)zone-(id) copyWithZone:(NSZone *)zone-(id) mutablecopyWithZone:(NSZone *)zone
10,NSTimer一定準(zhǔn)確么?怎么解決
-
主線程
NSTimer添加在主線程中,模式是NSDefaultRunLoopMode, 主線程處理所有添加在主線程中的事件,例如UI界面的刷新,復(fù)雜的運(yùn)算,等等,過(guò)多主線程事件的處理,導(dǎo)致線程阻塞;當(dāng)滑動(dòng)ScrollView的時(shí)候,Runlop會(huì)將Model切換到TrackingRunLoopMode,這時(shí)候的NSTimer事件就不會(huì)回調(diào),所以不準(zhǔn)解決:將
NSTimer添加到runloop的特定NSRunLoopCommonModes模式中[[NSRunLoop currentRunLoop] addTimer:timer1 forMode:NSRunLoopCommonModes]; -
子線程
子線程RunLoop默認(rèn)關(guān)閉,需手動(dòng)開啟,否則定時(shí)器不準(zhǔn),
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run];子線程定時(shí)器結(jié)束的時(shí)候,需要干掉,否則會(huì)造成資源的浪費(fèi)
[_timer invalidate]; _timer = nil;