
什么是對象 ,OC中的對象有哪些?
對象是類的實例;是通過一個類創(chuàng)建出來的實例,一般稱之為實例對象;OC中的常見對象有實例對象、類對象、元類對象;
什么是類?什么是元類?類對象和類,元類對象和元類有什么區(qū)別?
類: 是面向?qū)ο蟪绦蛟O(shè)計(OOP,Object-Oriented Programming)實現(xiàn)信息封裝的基礎(chǔ)。類是一種用戶定義的引用數(shù)據(jù)類型,也稱類類型。每個類包含數(shù)據(jù)說明和一組操作數(shù)據(jù)或傳遞消息的函數(shù)。類的實例稱為對象
元類:以類作為其實例的類;
類對象:類本身也是一個對象,所以就有類對象;類對象可以通過實例對象的ISA指針獲得
元類對象:元類本身也是一個對象,所以就有元類對象;元類對象可以通過類對象的ISA指針獲得
區(qū)分二者:
- 類、元類是面向?qū)ο缶幊讨械囊环N類型
- 類對象、元類對象是一種對象
什么是分類?
分類也是一個類,其底層結(jié)構(gòu)和類稍有不同;給分類添加的方法會在runtime 讀取鏡像,加載可執(zhí)行文件(_read_images)之后, 執(zhí)行remethodizeClass合并到原有類的方法列表(二維數(shù)組)中
分類多用來給類做擴展使用;在OC開發(fā)中應(yīng)用廣泛

什么是類擴展?
類擴展:用來給類擴充私有屬性、方法
什么是數(shù)組?
數(shù)組可表示為占用一塊連續(xù)的內(nèi)存空間用來存儲元素的數(shù)據(jù)結(jié)構(gòu);OC中的數(shù)組有可變和不可變兩種;可變數(shù)組做了優(yōu)化利用環(huán)形緩沖區(qū)技術(shù)提高增刪改查時的性能
什么是字典?
字典以鍵值的形式存儲數(shù)據(jù),底層實現(xiàn)是哈希表;OC對象作為可變字典的Key需要遵守NSCopying協(xié)議并且實現(xiàn)hash和isEqual兩個方法。比如:NSNumber、NSArray 、NSDictionary、自定義OC對象 都可以作為key
什么是集合?
集合是一種用來存儲數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),內(nèi)部存儲的數(shù)據(jù)時無序的,其他和數(shù)組相同
OC語法有哪些?
OC中的語法有點語法.,這里的點一般轉(zhuǎn)化為setter、getter方法調(diào)用
什么是Method?
Method是method_t的結(jié)構(gòu)體,是對一個方法的描述:
struct method_t{
SEL name; //函數(shù)名/方法名
const char *types;//編碼(返回值類型、參數(shù)類型)
IMP imp; //指向函數(shù)的指針(函數(shù)地址)
}
什么是內(nèi)斂函數(shù)?
- 內(nèi)聯(lián)函數(shù)基本概念
在c++中,預(yù)定義宏的概念是用內(nèi)聯(lián)函數(shù)來實現(xiàn)的,而內(nèi)聯(lián)函數(shù)本身也是一個真正的函數(shù)。內(nèi)聯(lián)函數(shù)具有普通函數(shù)的所有行為。唯一不同之處在于內(nèi)聯(lián)函數(shù)會在適當(dāng)?shù)牡胤较耦A(yù)定義宏一樣展開,所以不需要函數(shù)調(diào)用的開銷。因此應(yīng)該不使用宏,使用內(nèi)聯(lián)函數(shù)。
在普通函數(shù)(非成員函數(shù))函數(shù)前面加上inline關(guān)鍵字使之成為內(nèi)聯(lián)函數(shù)。但是必須注意必須函數(shù)體和聲明結(jié)合在一起,否則編譯器將它作為普通函數(shù)來對待。
inline void func(int a);
以上寫法沒有任何效果,僅僅是聲明函數(shù),應(yīng)該如下方式來做:
inline int func(int a){return ++;}
注意: 編譯器將會檢查函數(shù)參數(shù)列表使用是否正確,并返回值(進行必要的轉(zhuǎn)換)。
這些事預(yù)處理器無法完成的。
內(nèi)聯(lián)函數(shù)的確占用空間,但是內(nèi)聯(lián)函數(shù)相對于普通函數(shù)的優(yōu)勢只是省去了函數(shù)調(diào)用時候的壓棧,跳轉(zhuǎn),返回的開銷。我們可以理解為內(nèi)聯(lián)函數(shù)是以空間換時間。
-
類內(nèi)部的內(nèi)聯(lián)函數(shù)
為了定義內(nèi)聯(lián)函數(shù),通常必須在函數(shù)定義前面放一個inline關(guān)鍵字。但是在類內(nèi)部定義內(nèi)聯(lián)函數(shù)時并不是必須的。任何在類內(nèi)部定義的函數(shù)自動成為內(nèi)聯(lián)函數(shù)。
什么是構(gòu)造函數(shù)?
在一個類中定義一個和類名相同的函數(shù),這個函數(shù)就是構(gòu)造函數(shù)
面向?qū)ο蟮脑O(shè)計原則是什么 ?
單一責(zé)任原則、開閉原則、接口隔離原則、依賴倒置原則、里式替換原則、迪米特原則
- 單一責(zé)任原則
一個類只負責(zé)一件事情,CALayer只負責(zé)動畫和視圖的顯示,UIView只負責(zé)事件的傳遞、事件的響應(yīng) - 開閉原則
對修改關(guān)閉,對擴展開放; 要考慮API的后續(xù)擴展,而不是在原有基礎(chǔ)上來回修改 - 接口隔離原則
使用多協(xié)議的方式來定義接口,而不是一個臃腫的協(xié)議;比如delagate, datesource - 依賴倒置原則
抽象不應(yīng)該依賴具體實現(xiàn),具體實現(xiàn)依賴于抽象 - 里式替換原則
父類和子類無縫銜接,且原有功能不受影響;比如:KVO, 用完就走不留痕跡 - 迪米特原則
高內(nèi)聚,低耦合
面向?qū)ο笳Z言的三大特性是什么 ?
封裝、繼承、多態(tài)
OC的繼承體系
OC的繼承體系.png
關(guān)鍵字的使用標準?
ARC環(huán)境修飾OC對象用strong、copy、weak,修飾基本數(shù)據(jù)類型用assign;
靜態(tài)變量用static, 修飾為常量用const
關(guān)鍵字
常用設(shè)計模式?
設(shè)計模式分為四類:結(jié)構(gòu)型模式、創(chuàng)建型模式、行為型模式、軟件設(shè)計原則
常用的結(jié)構(gòu)型模式有:代理、裝飾
常用的創(chuàng)建型模式有:單利、工廠
常用的行為型模式有:觀察者、發(fā)布訂閱模式
代理:是一種消息傳遞方式,一個完整的代理模式包括:委托對象、代理對象和協(xié)議。
- 請代理三部曲:
1 定義代理協(xié)議
2 聲明delegate對象
3 調(diào)用代理方法 - 當(dāng)別人代理的三部曲
1 遵循協(xié)議
2 設(shè)置代理
3 實現(xiàn)方法
裝飾:動態(tài)地給一個類添加一些額外的職責(zé);Category 就是實現(xiàn)了裝飾的設(shè)計模式;Category是一個特殊的類,通過它可以給類添加方法的接口與實現(xiàn);
觀察者:包含通知和KVO
單利:單:唯一,例:實例;即唯一的一個實例,該實例自創(chuàng)建開始到程序退出由系統(tǒng)自動釋放;單利常被當(dāng)做共有類使用;
系統(tǒng)常見單利類
UIApplication(應(yīng)用程序?qū)嵗?
NSNotificationCenter(消息中心類)
NSFileManager(文件管理類)
NSUserDefaults(應(yīng)用程序設(shè)置)
NSURLCache(請求緩存類)
NSHTTPCookieStorage(應(yīng)用程序cookies池)
工廠模式:分為簡單工廠模式、工廠模式、抽象工廠模式
簡單工廠模式:簡單工廠模式是由一個工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實例。簡單工廠模式是工廠模式家族中最簡單實用的模式,可以理解為是不同工廠模式的一個特殊實現(xiàn)。
工廠模式:抽象了工廠接口的具體產(chǎn)品,應(yīng)用程序的調(diào)用不同工廠創(chuàng)建不同產(chǎn)品對象。(抽象產(chǎn)品)
抽象工廠模式:在工廠模式的基礎(chǔ)上抽象了工廠,應(yīng)用程序調(diào)用抽象的工廠發(fā)發(fā)創(chuàng)建不同產(chǎn)品對象。(抽象產(chǎn)品+抽象工廠)
懶加載:把初始化邏輯通過重寫的方式封裝起來,到需要時直接調(diào)用的方式
懶加載的優(yōu)點
- 相對來說,如果代碼量不是很多,可讀性略強
- 相對來說,防止為nil,減少了后續(xù)使用時安全檢查的后顧之憂
- 使用適當(dāng),可節(jié)省內(nèi)存資源
- 一定程度上,節(jié)省了某一個期間內(nèi)的時間
- 使用得當(dāng),優(yōu)化性能,提高用戶體驗
懶加載的缺點 - 使用太泛濫,導(dǎo)致可讀性變差
- 使用不得當(dāng),可能會造成死循環(huán),導(dǎo)致crash
- 代碼量增多(每增加一個懶加載,代碼會平均多出3-4行)
什么時候使用懶加載?
一般情況下,不需要使用懶加載,懶加載未必能增強可讀性、獨立性,濫用反而讓可讀性適得其反。簡言之,就是在邏輯上,覺得現(xiàn)在不需要加載,而在后面某一時間段內(nèi)可能會加載,就可以考慮懶加載
生產(chǎn)者消費者:
在編碼中,有時會遇到一個模塊產(chǎn)生數(shù)據(jù),另外一個模塊處理數(shù)據(jù)的情況,不論是為了模塊間的結(jié)偶或是并發(fā)處理還是忙閑不均,我們都會在產(chǎn)生和處理數(shù)據(jù)的模塊之間放置緩存區(qū),作為生產(chǎn)和處理數(shù)據(jù)的倉庫。以上的模型就是生產(chǎn)者消費者模型
生產(chǎn)者-消費者
中介者:
- 中介者模式又叫做調(diào)停者模式,其實就是中間人或者調(diào)停者的意思
- 概念:中介者模式(Mediator),用一個中介者對象來封裝一系列的對象交互。中介者使各個對象不需要顯式地相互引用,從而使其耦合松散,而且可 以獨立地改變他們之間的交互
- UINavigationViewController就是屬于一個中介者
- 中介者模式的優(yōu)缺點
中介者模式很容易在系統(tǒng)中應(yīng)用,也很容易在系統(tǒng)中誤用。當(dāng)系統(tǒng)出現(xiàn)了多對多交互復(fù)雜的對象群時,不要急于使用中介者模式,而要先反思你在系統(tǒng)上設(shè)計是否合理。
優(yōu)點就是集中控制,減少了對象之間的耦合度。缺點就是太過于集中 - 應(yīng)用場景
對象間的交互雖定義明確然而非常復(fù)雜,導(dǎo)致一組對象彼此相互依賴而且難以理解。
因為對象引用了許多其他對象并與其通信,導(dǎo)致對象難以復(fù)用。
想要定制一個分布在多個類中的邏輯或者行為,又不想生成太多子類
發(fā)布訂閱模式
其實基本的設(shè)計模式中并沒有發(fā)布訂閱模式,上面也說了,他只是觀察者模式的一個別稱。但是經(jīng)過時間的沉淀,似乎他已經(jīng)強大了起來,已經(jīng)獨立于觀察者模式,成為另外一種不同的設(shè)計模式。
在現(xiàn)在的發(fā)布訂閱模式中,稱為發(fā)布者的消息發(fā)送者不會將消息直接發(fā)送給訂閱者,這意味著發(fā)布者和訂閱者不知道彼此的存在。在發(fā)布者和訂閱者之間存在第三個組件,稱為消息代理或調(diào)度中心或中間件,它維持著發(fā)布者和訂閱者之間的聯(lián)系,過濾所有發(fā)布者傳入的消息并相應(yīng)地分發(fā)它們給訂閱者。
舉一個例子,你在微博上關(guān)注了A,同時其他很多人也關(guān)注了A,那么當(dāng)A發(fā)布動態(tài)的時候,微博就會為你們推送這條動態(tài)。A就是發(fā)布者,你是訂閱者,微博就是調(diào)度中心,你和A是沒有直接的消息往來的,全是通過微博來協(xié)調(diào)的(你的關(guān)注,A的發(fā)布動態(tài)
觀察者模式和發(fā)布訂閱模式有什么區(qū)別?
觀察者模式: 觀察者(Observer)直接訂閱(Subscribe)主題(Subject),而當(dāng)主題被激活的時候,會觸發(fā)(Fire Event)觀察者里的事件。
發(fā)布訂閱模式: 訂閱者(Subscriber)把自己想訂閱的事件注冊(Subscribe)到調(diào)度中心(Topic),當(dāng)發(fā)布者(Publisher)發(fā)布該事件(Publish topic)到調(diào)度中心,也就是該事件觸發(fā)時,由調(diào)度中心統(tǒng)一調(diào)度(Fire Event)訂閱者注冊到調(diào)度中心的處理代碼。常見的是用協(xié)議的方式來做
- 觀察者模式是不是發(fā)布訂閱模式
網(wǎng)上關(guān)于這個問題的回答,出現(xiàn)了兩極分化,有認為發(fā)布訂閱模式就是觀察者模式的,也有認為觀察者模式和發(fā)布訂閱模式是真不一樣的。
其實我不知道發(fā)布訂閱模式是不是觀察者模式,就像我不知道辨別模式的關(guān)鍵是設(shè)計意圖還是設(shè)計結(jié)構(gòu)(理念),雖然《JavaScript設(shè)計模式與開發(fā)實踐》一書中說了分辨模式的關(guān)鍵是意圖而不是結(jié)構(gòu)。
如果以結(jié)構(gòu)來分辨模式,發(fā)布訂閱模式相比觀察者模式多了一個中間件訂閱器,所以發(fā)布訂閱模式是不同于觀察者模式的;如果以意圖來分辨模式,他們都是實現(xiàn)了對象間的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都將得到通知,并自動更新,那么他們就是同一種模式,發(fā)布訂閱模式是在觀察者模式的基礎(chǔ)上做的優(yōu)化升級。
不過,不管他們是不是同一個設(shè)計模式,他們的實現(xiàn)方式確實有差別,我們在使用的時候應(yīng)該根據(jù)場景來判斷選擇哪個
block
- block是封裝了函數(shù)調(diào)用和函數(shù)調(diào)用環(huán)境的OC對象,block分為3種類型:NSGlobalBlock、NSStackBlock、NSMallocBlock; 其都繼承自NSBlock,NSBlock 繼承自NSObject;
- block使用需注意循環(huán)引用問題;一般需要使用強弱引用、__block來解決問題
- block聲明為屬性時需要使用copy或strong來修飾;因為block最初是被分配在??臻g,內(nèi)存由系統(tǒng)管理;但一般使用block是需要在運行時的某一個時機使用,所以需要開發(fā)者自己管理block的內(nèi)存,使用copy和strong修飾會把block的內(nèi)存復(fù)制到堆空間,這樣就達到了自己管理內(nèi)存的目的
為什么block一開始的內(nèi)存會被分配在??臻g?
block使用會有兩種情況:局部變量、typedef聲明
局部變量申請的內(nèi)存肯定在棧空間
對象的本質(zhì)?
對象的本質(zhì)是結(jié)構(gòu)體;
內(nèi)存分配原理:以16個字節(jié)為單位且遵循了內(nèi)存對齊原則向堆內(nèi)存申請內(nèi)存空間
isa指針?
isa指針是OC對象的第一個成員變量;isa是一個聯(lián)合體結(jié)構(gòu),通過位域來存儲數(shù)據(jù);
isa最重要的作用是用于消息發(fā)送;
位域宏定義(真機環(huán)境arm64)
# if __arm64__
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
# define ISA_BITFIELD \
uintptr_t nonpointer : 1; 拿二進制的1位來存儲 \
uintptr_t has_assoc : 1; \
uintptr_t has_cxx_dtor : 1; \
uintptr_t shiftcls : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
uintptr_t magic : 6; \
uintptr_t weakly_referenced : 1; \
uintptr_t deallocating : 1; \
uintptr_t has_sidetable_rc : 1; \
uintptr_t extra_rc : 19
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
OC的內(nèi)存管理原則 ?
OC中內(nèi)存管理是通過引用計數(shù)管理實現(xiàn)的,當(dāng)一個對象的引用計數(shù)為0時就會進入釋放流程;ARC利用LLVM編譯器動態(tài)的在合適的位置添加內(nèi)存管理代碼的方式幫助開發(fā)者管理內(nèi)存,同時又通過runtime管理weak修飾的弱引用表;基本實現(xiàn)了不用開發(fā)者關(guān)心內(nèi)存問題就可以進行開發(fā);
- block、定時器時需要注意循環(huán)引用問題
- 聲明屬性時需要注意強弱引用的使用
多線程?
即 multithreading , 是指從軟件或者硬件上實現(xiàn)多個線程并發(fā)執(zhí)行的技術(shù)。
具有多線程能力的計算機因有硬件支持而能夠在同一時間執(zhí)行多于一個線程,進而提升整體處理性能。具有這種能力的系統(tǒng)包括對稱多處理機、多核心處理器以及芯片級多處理(Chip-level multithreading)或同時多線程(Simultaneous multithreading)處理器。在一個程序中,這些獨立運行的程序片段叫作“線程”(Thread),利用它編程的概念就叫作“多線程處理(Multithreading)”。
多線程的調(diào)度原理可以認為是:時間片輪轉(zhuǎn)調(diào)度算法,每個線程都會分配一個時間片然后大家輪著做任務(wù),多線程執(zhí)行時會快速切換時間片來完成多線程任務(wù)的執(zhí)行;其實操作系統(tǒng)對進程、線程都是按照這種調(diào)度邏輯實現(xiàn)的
程序、進程、線程、例程、協(xié)程是什么?
程序:全稱 計算機程序(Computer Program),是一組計算機能識別和執(zhí)行的指令,又稱計算機軟件
是指為了得到某種結(jié)果而可以由計算機等具有信息處理能力的裝置執(zhí)行的代碼化指令序列,用某些程序設(shè)計語言編寫,如:C、C++、OC等;它運行于電子計算機上進程:是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動;是獨立運行、獨立分配資源和獨立接受調(diào)度的基本單位;是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)
在當(dāng)代面向線程設(shè)計的計算機結(jié)構(gòu)中,進程是線程的容器。程序是指令、數(shù)據(jù)及其組織形式的描述,進程是程序的實體
線程:線程是計算機調(diào)度的最小單位,用來處理不同的任務(wù);
例程:即函數(shù),一個函數(shù)就可以看做是一個例程
協(xié)程:利用單線程執(zhí)行多任務(wù)的技術(shù)解決方案,性能上避免線程間切換要優(yōu)于線程調(diào)度;是線程的更小拆分,又稱之為“微線程”,是一種用戶太的輕量級線程;
和線程的區(qū)別:
線程是系統(tǒng)級別的,它們由操作系統(tǒng)調(diào)度;同時是可被調(diào)度的最小單位;
協(xié)程則是程序級別的,由程序員根據(jù)需要自己調(diào)度
子程序:函數(shù)
在一個線程中會有很多子程序,在子程序執(zhí)行過程中可以中斷去執(zhí)行別的子程序,而別的子程序也可以中斷回來繼續(xù)執(zhí)行之前的子程序,這個過程及稱為協(xié)程。也就是說在同一線程內(nèi)一段代碼在執(zhí)行過程中會中斷然后跳轉(zhuǎn)執(zhí)行別的代碼,接著在之前中斷的地方繼續(xù)開始執(zhí)行,類似于yield操作
實例的生命周期?
- alloc、new、copy、mutableCopy
- 引用計數(shù)變化
- 引用計數(shù)為0
- dealloc
控制器的生命周期?
控制器的聲明周期
響應(yīng)者鏈條?
