GitHub: https://github.com/LiCheng244/LCUtils
個(gè)人博客: http://www.licheng244.com/
1. Object-c的類可以多重繼承么更舞?可以實(shí)現(xiàn)多個(gè)接口么阻星?Category是什么锨侯?重寫一個(gè)類的方式用繼承好還是分類好慢显?為什么俗慈?
Object-c的類不可以多重繼承;可以實(shí)現(xiàn)多個(gè)接口召边,通過實(shí)現(xiàn)多個(gè)接口可以完成C++的多重繼承稳吮;Category是類別,又叫分類际看;一般情況用分類好咸产,用Category去重寫類的方法,僅對(duì)本Category有效仲闽,不會(huì)影響到其他類與原有類的關(guān)系脑溢。
2. #import 跟#include 又什么區(qū)別,@class呢, #import<> 跟 #import”"又什么區(qū)別赖欣?
import是Objective-C導(dǎo)入頭文件的關(guān)鍵字;
include是C/C++導(dǎo)入頭文件的關(guān)鍵字;
使用#import頭文件會(huì)自動(dòng)只導(dǎo)入一次屑彻,不會(huì)重復(fù)導(dǎo)入,相當(dāng)于#include和#pragma once顶吮;
c語言解決重復(fù)導(dǎo)入頭文件的方法是:在頭文件的最開始加上宏定義的方法(MYLIB_H)社牲。
@class告訴編譯器某個(gè)類只是一個(gè)類名,當(dāng)執(zhí)行時(shí)悴了,才去查看類的實(shí)現(xiàn)文件搏恤,可以解決頭文件的相互包含违寿;這種寫法叫做類的前置聲明。
import<>用來包含系統(tǒng)的頭文件熟空,#import””用來包含用戶頭文件藤巢。
3. 屬性readwrite,readonly息罗,assign掂咒,retain,copy迈喉,nonatomic 各是什么作用绍刮,在那種情況下用?
readwrite 是可讀可寫特性挨摸;需要生成getter方法和setter方法時(shí)
readonly 是只讀特性 只會(huì)生成getter方法 不會(huì)生成setter方法 ;不希望屬性在類外改變
assign 是賦值特性孩革,setter方法將傳入?yún)?shù)賦值給實(shí)例變量;僅設(shè)置變量時(shí)得运;
retain 表示持有特性嫉戚,setter方法將傳入?yún)?shù)先保留,再賦值澈圈,傳入?yún)?shù)的retaincount會(huì)+1;
copy 表示拷貝特性彬檀,setter方法將傳入對(duì)象復(fù)制一份;需要完全一份新的變量時(shí)瞬女。
nonatomic 非原子操作窍帝,決定編譯器生成的setter getter是否是原子操作,atomic表示多線程安全诽偷,一般使用nonatomic
4. 寫一個(gè)setter方法用于完成@property (nonatomic,retain)NSString *name,寫一個(gè)setter方法用于完成@property(nonatomic坤学,copy)NSString *name
- (void)setName:(NSString *) str
{
[str retain];
[name release];
name = str;
} - (void)setName:(NSString *)str
{
id t = [str copy];
[name release];
name = t;
}
######5. 對(duì)于語句NSString*obj = [[NSData alloc] init]; obj在編譯時(shí)和運(yùn)行時(shí)分別時(shí)什么類型的對(duì)象?
>編譯時(shí)是NSString的類型报慕;運(yùn)行時(shí)是NSData類型的對(duì)象
######6. 常見的object-c的數(shù)據(jù)類型有那些深浮, 和C的基本數(shù)據(jù)類型有什么區(qū)別?如:NSInteger和int
>object-c的數(shù)據(jù)類型有NSString眠冈,NSNumber飞苇,NSArray,NSMutableArray蜗顽,NSData等等布卡,這些都是class,創(chuàng)建后便是對(duì)象雇盖。
而[C語言](http://lib.csdn.net/base/c)的基本數(shù)據(jù)類型int忿等,只是一定字節(jié)的內(nèi)存空間,用于存放數(shù)值崔挖;
NSInteger是基本數(shù)據(jù)類型贸街,并不是NSNumber的子類庵寞,當(dāng)然也不是NSObject的子類。NSInteger是基本數(shù)據(jù)類型Int或者Long的別名(NSInteger的定義typedef long NSInteger)薛匪,它的區(qū)別在于皇帮,NSInteger會(huì)根據(jù)系統(tǒng)是32位還是64位來決定是本身是int還是Long。
######7. id 聲明的對(duì)象有什么特性蛋辈?
>Id 聲明的對(duì)象具有運(yùn)行時(shí)的特性,即可以指向任意類型的objcetive-c的對(duì)象将谊;
######8. Objective-C如何對(duì)內(nèi)存管理的,說說你的看法和解決方法?
>Objective-C的內(nèi)存管理主要有三種方式ARC(自動(dòng)內(nèi)存計(jì)數(shù))冷溶、手動(dòng)內(nèi)存計(jì)數(shù)、內(nèi)存池尊浓。
######9. 內(nèi)存管理的幾條原則時(shí)什么逞频?按照默認(rèn)法則.哪些關(guān)鍵字生成的對(duì)象需要手動(dòng)釋放?在和property結(jié)合的時(shí)候怎樣有效的避免內(nèi)存泄露栋齿?
>誰申請(qǐng)苗胀,誰釋放。遵循Cocoa Touch的使用原則瓦堵;
內(nèi)存管理主要要避免“過早釋放”和“內(nèi)存泄漏”基协,對(duì)于“過早釋放”需要注意@property設(shè)置特性時(shí),一定要用對(duì)特性關(guān)鍵字菇用,對(duì)于“內(nèi)存泄漏”澜驮,一定要申請(qǐng)了要負(fù)責(zé)釋放,要細(xì)心惋鸥。
關(guān)鍵字alloc 或new 生成的對(duì)象需要手動(dòng)釋放杂穷;
設(shè)置正確的property屬性,對(duì)于retain需要在合適的地方釋放卦绣。
######10. 如何對(duì)iOS設(shè)備進(jìn)行性能測試?
>Profile-> Instruments ->Time Profiler
######11. Object C中創(chuàng)建線程的方法是什么耐量?如果在主線程中執(zhí)行代碼,方法是什么滤港?如果想延時(shí)執(zhí)行代碼廊蜒、方法又是什么?
>線程創(chuàng)建有三種方法:`使用NSThread創(chuàng)建`溅漾、`使用GCD的dispatch`劲藐、`使用子類化的NSOperation,然后將其加入NSOperationQueue`;
在主線程執(zhí)行代碼,方法是`performSelectorOnMainThread`;
如果想延時(shí)執(zhí)行代碼可以用`performSelector:onThread:withObject: afterDelay:` 或者使用GCD的函數(shù): `
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{// 2秒后異步執(zhí)行這里的代碼...});`
######12. 淺復(fù)制和深復(fù)制的區(qū)別樟凄?
>**淺層復(fù)制:**只復(fù)制指向?qū)ο蟮闹羔樒肝撸粡?fù)制引用對(duì)象本身。
**深層復(fù)制:**復(fù)制引用對(duì)象本身缝龄。
意思就是說我有個(gè)A對(duì)象汰现,復(fù)制一份后得到A_copy對(duì)象后挂谍,對(duì)于淺復(fù)制來說,A和A_copy指向的是同一個(gè)內(nèi)存資源瞎饲,復(fù)制的只不過是是一個(gè)指針口叙,對(duì)象本身資源還是只有一份,那如果我們對(duì)A_copy執(zhí)行了修改操作,那么發(fā)現(xiàn)A引用的對(duì)象同樣被修改嗅战,這其實(shí)違背了我們復(fù)制拷貝的一個(gè)思想妄田。深復(fù)制就好理解了,內(nèi)存中存在了兩份獨(dú)立對(duì)象本身。
**用網(wǎng)上一哥們通俗的話將就是:**
淺復(fù)制好比你和你的影子驮捍,你完蛋疟呐,你的影子也完蛋
深復(fù)制好比你和你的克隆人,你完蛋东且,你的克隆人還活著启具。
######13. 類別的作用?繼承和類別在實(shí)現(xiàn)中有何區(qū)別珊泳?
>類別主要有3個(gè)**作用:**
(1) 將類的實(shí)現(xiàn)分散到多個(gè)不同文件或多個(gè)不同框架中鲁冯。
(2) 創(chuàng)建對(duì)私有方法的前向引用。
(3) 向?qū)ο筇砑臃钦絽f(xié)議色查。
**category:** 可以在不獲悉薯演,不改變?cè)瓉泶a的情況下往里面添加新的方法,只能添加秧了,不能刪除修改涣仿。并且如果類別和原來類中的方法產(chǎn)生名稱沖突,則類別將覆蓋原來的方法示惊,因?yàn)轭悇e具有更高的優(yōu)先級(jí)好港。
**繼承:** 可以增加、擴(kuò)展父類方法米罚,并且可以增加屬性钧汹。
######14. 類別和類擴(kuò)展的區(qū)別?
>category和extensions的不同在于 extensions可以添加屬性。另外extensions添加的方法是必須要實(shí)現(xiàn)的录择。extensions可以認(rèn)為是一個(gè)私有的Category拔莱。
######15. 代理的作用?
>代理的目的是改變或傳遞控制鏈隘竭。允許一個(gè)類在某些特定時(shí)刻通知到其他類塘秦,而不需要獲取到那些類的指針《矗可以減少框架復(fù)雜度尊剔。另外一點(diǎn),代理可以理解為java中的回調(diào)監(jiān)聽機(jī)制的一種類似菱皆。
######16. 什么是推送消息须误?
>iOS中消息推送機(jī)制又叫消息機(jī)制挨稿,其包括兩類:一類是**本地通知**;另一類是推送通知京痢,也叫**遠(yuǎn)程通知**奶甘。
兩種通知在iOS中的表現(xiàn)一致,可以通過橫幅或者彈出提醒兩種形式告訴用戶祭椰,并且點(diǎn)擊通知可以會(huì)打開應(yīng)用程序臭家。
但是實(shí)現(xiàn)原理卻完全不同:
**本地通知: **是由本地應(yīng)用觸發(fā)的,它是基于時(shí)間行為的一種通知形式;
**推送通知:**是由應(yīng)用服務(wù)提供商發(fā)起的方淤,通過蘋果的APNs(Apple Push Notification Server)發(fā)送到應(yīng)用客戶端,如下圖:![](http://upload-images.jianshu.io/upload_images/1975627-3d0fc96dc7372a95?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
######17. 什么時(shí)候使用NSMutableArray钉赁,什么時(shí)候使用NSArray?
>當(dāng)數(shù)組在程序運(yùn)行時(shí)臣淤,需要不斷變化的,使用NSMutableArray;
當(dāng)數(shù)組在初始化后窃爷,便不再改變的邑蒋,使用NSArray。
需要指出的是按厘,使用NSArray只表明的是該數(shù)組在運(yùn)行時(shí)不發(fā)生改變医吊,即不能往NSAarry的數(shù)組里新增和刪除元素,但不表明其數(shù)組內(nèi)的元素的內(nèi)容不能發(fā)生改變逮京。
NSArray是線程安全的卿堂,NSMutableArray不是線程安全的,多線程使用到NSMutableArray需要注意懒棉。
######17. frame和bounds有什么不同草描?
>**frame**指的是:該view在父view坐標(biāo)系統(tǒng)中的位置和大小。(參照點(diǎn)是父親的坐標(biāo)系統(tǒng))
**bounds**指的是:該view在本身坐標(biāo)系統(tǒng)中 的位置和大小策严。(參照點(diǎn)是本身坐標(biāo)系統(tǒng))
######18. 談?wù)凮bject-C的內(nèi)存管理方式及過程穗慕?
>1). 當(dāng)你使用new,alloc和copy方法創(chuàng)建一個(gè)對(duì)象時(shí),該對(duì)象的保留計(jì)數(shù)器值為1.當(dāng)你不再使用該對(duì)象時(shí),你要負(fù)責(zé)向該對(duì)象發(fā)送一條release或autorelease消息.這樣,該對(duì)象將在使用壽命結(jié)束時(shí)被銷毀.
2). 當(dāng)你通過任何其他方法獲得一個(gè)對(duì)象時(shí),則假設(shè)該對(duì)象的保留計(jì)數(shù)器值為1,而且已經(jīng)被設(shè)置為自動(dòng)釋放,你不需要執(zhí)行任何操作來確保該對(duì)象被清理.如果你打算在一段時(shí)間內(nèi)擁有該對(duì)象,則需要保留它并確保在操作完成時(shí)釋放它.
3). 如果你保留了某個(gè)對(duì)象,你需要(最終)釋放或自動(dòng)釋放該對(duì)象.必須保持retain方法和release方法的使用次數(shù)相等.
######19. Objective-C堆和棧的區(qū)別?
>**管理方式:**
對(duì)于棧來講妻导,是由編譯器自動(dòng)管理逛绵,無需我們手工控制;
對(duì)于堆來說倔韭,釋放工作由程序員控制术浪,容易產(chǎn)生memory leak。
**申請(qǐng)大惺僮谩:**
**棧:**在Windows下,棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)胰苏,是一塊連續(xù)的內(nèi)存的區(qū)域。這句話的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的醇疼,在 WINDOWS下碟联,棧的大小是2M(也有的說是1M妓美,總之是一個(gè)編譯時(shí)就確定的常數(shù)),如果申請(qǐng)的空間超過棧的剩余空間時(shí)鲤孵,將提示overflow壶栋。因此,能從棧獲得的空間較小普监。
**堆:**堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)贵试,是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來存儲(chǔ)的空閑內(nèi)存地址的凯正,自然是不連續(xù)的毙玻,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計(jì)算機(jī)系統(tǒng)中有效的虛擬內(nèi)存廊散。由此可見桑滩,堆獲得的空間比較靈活,也比較大允睹。
碎片問題:對(duì)于堆來講运准,頻繁的new/delete勢必會(huì)造成內(nèi)存空間的不連續(xù),從而造成大量的碎片缭受,使程序效率降低胁澳。對(duì)于棧來講,則不會(huì)存在這個(gè)問題米者,因?yàn)闂J窍冗M(jìn)后出的隊(duì)列韭畸,他們是如此的一一對(duì)應(yīng),以至于永遠(yuǎn)都不可能有一個(gè)內(nèi)存塊從棧中間彈出
**分配方式:**
堆都是動(dòng)態(tài)分配的蔓搞,沒有靜態(tài)分配的堆胰丁。
棧有2種分配方式:靜態(tài)分配和動(dòng)態(tài)分配。
靜態(tài)分配是編譯器完成的喂分,比如局部變量的分配隘马。
動(dòng)態(tài)分配由alloca函數(shù)進(jìn)行分配,但是棧的動(dòng)態(tài)分配和堆是不同的妻顶,他的動(dòng)態(tài)分配是由編譯器進(jìn)行釋放酸员,無需我們手工實(shí)現(xiàn)。
**分配效率:**
棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu)讳嘱,計(jì)算機(jī)會(huì)在底層對(duì)棧提供支持:分配專門的寄存器存放棧的地址幔嗦,壓棧出棧都有專門的指令執(zhí)行,這就決定了棧的效率比較高沥潭。
堆則是C/C++函數(shù)庫提供的邀泉,它的機(jī)制是很復(fù)雜的。
######20. static 關(guān)鍵字的作用?
>1). 函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量汇恤,該變量的內(nèi)存只被分配一次庞钢,
因此其值在下次調(diào)用時(shí)仍維持上次的值;
2). 在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問因谎,但不能被模塊外其它函數(shù)訪問基括;
3). 在模塊內(nèi)的 static 函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個(gè)函數(shù)的使用范圍被限制在聲明它的模塊內(nèi)财岔;
4). 在類中的 static 成員變量屬于整個(gè)類所擁有风皿,對(duì)類的所有對(duì)象只有一份拷貝;
5). 在類中的 static 成員函數(shù)屬于整個(gè)類所擁有匠璧,這個(gè)函數(shù)不接收 this 指針桐款,因而只能訪問類的static 成員變量。
######21. 線程與進(jìn)程的區(qū)別和聯(lián)系?
>1). 進(jìn)程和線程都是由操作系統(tǒng)所體會(huì)的程序運(yùn)行的基本單元夷恍,系統(tǒng)利用該基本單元實(shí)現(xiàn)系統(tǒng)對(duì)應(yīng)用的并發(fā)性
2). 進(jìn)程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式魔眨。
3). 進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后酿雪,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響遏暴,而線程只是一個(gè)進(jìn)程中的不同執(zhí)行路徑。
4). 線程有自己的堆棧和局部變量执虹,但線程之間沒有單獨(dú)的地址空間拓挥,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉唠梨。所以多進(jìn)程的程序要比多線程的程序健壯袋励,但在進(jìn)程切換時(shí),耗費(fèi)資源較大当叭,效率要差一些茬故。
5). 但對(duì)于一些要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程蚁鳖,不能用進(jìn)程磺芭。
######22. 關(guān)于靜態(tài)變量static?
>在函數(shù)或方法范圍外定義的變量以及用static修飾的變量都是靜態(tài)變量。靜態(tài)變量的生命周期是從程序開始到程序結(jié)束醉箕。
類方法中可以使用帶有static修飾的靜態(tài)變量, 但是無論生成多少該類的對(duì)象, 都只有一個(gè)靜態(tài)變量, 也就是說多個(gè)對(duì)象共享一個(gè)靜態(tài)變量钾腺。
一個(gè)對(duì)象對(duì)靜態(tài)變量賦值后, 在使用這個(gè)變量之前, 如果有另外一個(gè)對(duì)象修改了該靜態(tài)變量的值, 如果不進(jìn)行同步的話就會(huì)發(fā)生錯(cuò)誤。
利用靜態(tài)變量的這種性質(zhì)可以實(shí)現(xiàn)對(duì)象間的信息共享和消息傳遞等讥裤。
######23. super 和 self 的區(qū)別?
>**super: ** super和self不同, 并不確定指向某個(gè)對(duì)象放棒。super只能被用于調(diào)用父類的方法, 不能通過super完成賦值, 也不能把方法的返回值指定為super。
**self: ** 是指收到當(dāng)前消息的實(shí)例變量, 例如:B類繼承A類, B類方法中調(diào)用[self a]; B類中沒有a方法, 是繼承自A類中的, A類中a方法調(diào)用了b方法[self b]; , 此時(shí)這個(gè)self 指的是B類的對(duì)象己英。
######24. 動(dòng)態(tài)綁定?
>**動(dòng)態(tài)綁定: **在程序執(zhí)行時(shí)才確定對(duì)象的屬性和需要響應(yīng)的消息间螟。
OC中的消息是執(zhí)行時(shí)才去綁定的。運(yùn)行時(shí)系統(tǒng)首先會(huì)確定接受者的類型(動(dòng)態(tài)類型識(shí)別),然后根據(jù)消息名在類的方法列表里選擇響應(yīng)的方法執(zhí)行,如果沒有就到父類中繼續(xù)尋找, 如果一直到NSObject也沒有找到要調(diào)用的方法, 就會(huì)包不能識(shí)別消息的錯(cuò)誤。
######25. nil 和 null 等等.
>**nil: **空指針, 表示一個(gè)空的對(duì)象, 這個(gè)的對(duì)象的指針指向空厢破。值為0荣瑟。初始化方法失敗的時(shí)候通常會(huì)返回nil。
######26. 靜態(tài)類型檢查的總結(jié)
>OC的靜態(tài)類型檢查是在編譯期完成的摩泪。
>1). 對(duì)于id類型的變量, 調(diào)用任何方法都會(huì)通過編譯(當(dāng)然調(diào)用不恰當(dāng)?shù)姆椒〞?huì)出現(xiàn)運(yùn)行時(shí)錯(cuò)誤)
2). id類型的變量和被靜態(tài)類型的變量之間是可以相互賦值的
3). 被定義為靜態(tài)類型對(duì)象的變量, 如果調(diào)用了類或父類中未定義的方法, 編譯器就會(huì)提示警告
4). 如果是靜態(tài)類型的變量, 父類類型的實(shí)例變量不可以賦值給子類類型的實(shí)例變量
5). 如果是靜態(tài)類型的變量, 子類類型的實(shí)例變量可以賦值給父類類型的實(shí)例變量
6). 若要判斷到底是哪一個(gè)類的方法被執(zhí)行了, 不要看變量所聲明的類型, 而要看司機(jī)執(zhí)行時(shí)這個(gè)變量的類型
7). id類型并不是(NSObject *)類型
######27. 重載
> **重載: **指的是一個(gè)函數(shù)笆焰、運(yùn)算符或者方法定義有多種功能, 并根據(jù)情況來選擇合適的功能。
OC 可以通過動(dòng)態(tài)綁定讓同一個(gè)消息選擇器執(zhí)行不同的功能來實(shí)現(xiàn)重載加勤。
######28. 為什么不可以直接訪問屬性, 而是要通過getter 和 setter方法來實(shí)現(xiàn)?
>為了封裝仙辟。
如果允許直接訪問類的實(shí)例變量, 那么當(dāng)類的實(shí)現(xiàn)發(fā)生了變化, 實(shí)例變量被刪除或者作用發(fā)生了變化時(shí), 所有調(diào)用這個(gè)類的外部模塊都需要修改。
如果使用類getter/setter的形式, 當(dāng)類的實(shí)現(xiàn)發(fā)生了變化時(shí)則只需要修改getter/setter接口, 外部調(diào)用部分不需要做任何修改鳄梅。
雖然子類可以直接訪問父類的實(shí)例變量, 但是要盡量用getter/setter方法來訪問父類中的實(shí)例變量, 這樣可以使程序盡可能的低耦合叠国。
######29. 實(shí)例變量的可見性
>三種修飾符: private、protected戴尸、public
![](http://upload-images.jianshu.io/upload_images/1975627-eda82138d45f322e.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)