OC基础知识(面试必看)
OC基礎知識
一、屬性和關鍵字
·成員變量與屬性的區別:聲明了@property并@synthesize后編譯器會為實例變量生成getter和setter方法,成員變量用來存儲屬性的值
·修飾屬性的關鍵字: atomic/nonatomic readwrite/readonly assign/weak retain/strong/copy/ (weak/strong只能在arc下使用)
引入其他文件中聲明的全局變量時,使用extern 關鍵字
·屬性默認修飾關鍵字:atomic,readwrite
·原子性操作:要么都執行,要么都不執行(atomic原子操作能保證多線程安全)
·野指針:用strong或者weak修飾的對象的retainCount為0時,屬性會被置為nil,不會造成野指針,不會引起崩潰,而用retain/assign 修飾的對象retainCount為0時,是不會進行任何操作的,如果再用屬性去調用該對象時,可能會有崩潰現象,野指針操作
·copy與strong的區別:copy會開辟新內存復制一份新的數據
·retain與strong的區別:strong只能在arc下使用,
·copy與mutablecopy的區別:
copy:對不可變對象copy是淺拷貝,對可變對象copy是深拷貝
mutableCopy:一定是深拷貝
(深拷貝時,copy出的是不可變對象,mutablecopy出的是可變對象)
自定義對象copy:遵守NSCopying,NSMutableCopying協議,實現copyWithZone mutableCopyWithZone 方法
NSArray用copy修飾,NSMutableArray用strong修飾
二、block和代理
“閉包(Closure)是由函數和與其相關的引用環境組合而成的實體.” block就是OC對閉包的實現
block 本質應該是一個函數指針加上一個對應捕獲上下文變量的內存塊(結構體或者類)
Block當做Objective-C的匿名函數
block是代碼塊,其本質和變量類似
1、什么是block?
block其實就是一個代碼塊,把你想要執行的代碼封裝在這個代碼塊里,等到需要的時候再去調用。那block是OC對象嗎?答案是肯定的
2、block要用copy修飾,還是用strong
block變量默認是聲明為棧變量的,為了能夠在block的聲明域外使用,所以要把block拷貝(copy)到堆,所以說為了block屬性聲明和實際的操作一致,最好聲明為copy。
在聲明Block時,使用strong和retain會有截然不同的效果。strong等于copy,retain等于assign
3、block有幾種
在 iOS中, block一共分三種。
(1)全局靜態 block,不會訪問任何外部變量,執行完就銷毀。
(2)保存在棧中的 block,當函數返回時會被銷毀,和第一種的區別就是調用了外部變量。
(3)保存在堆中的 block,當引用計數為 0 時會被銷毀。例如按鈕的點擊事件,一直存在,即使執行過,也不銷毀,因為按鈕還可能被點擊,持有按鈕的View被銷毀,它才會被銷毀。
4、__block關鍵字的使用
在Block的{}體內,是不可以對外面的變量進行更改的,使用__block就能改變block塊中變量的值
5、__block和__weak的區別?
(1)__block不管是ARC還是MRC模式下都可以使用,可以修飾對象,還可以修飾基本數據類型。?
(2)__weak只能在ARC模式下使用,也只能修飾對象(NSString),不能修飾基本數據類型(int)。?
(3)__block對象可以在block中被重新賦值,__weak不可以。?
(4)__block對象在ARC下可能會導致循環引用,非ARC下會避免循環引用,__weak只在ARC下使用,可以避免循環引用。
6、block與代理的區別:(都是一對一,通知是一對多)
(1)block 更輕型,使用更簡單,代碼易讀,能夠直接訪問上下文,使用不當會造成循環引用
(2)代理降低了類之間的耦合性,它的相關代碼會被分離到各處,沒有 block 好讀
(3)delegate運行成本低,block的運行成本高。block出棧需要將使用的數據從棧內存拷貝到堆內存,當然對象的話就是加計數,使用完或者block置nil后才消除。delegate只是保存了一個對象指針,直接回調
(4)如果回調只有一種或兩種情況的時候,使用block進行回調比較方法,如果有多種回調情況的,采用協議代理
三、類和對象
·OC 中的拓展方法:類別、協議、延展、繼承
//用類別可以添加屬性,但是實現的時候要借助runtime 添加鍵值對和訪問權限
//延展:選擇性公開在原類實現文件中聲明的成員變量、屬性、和方法
·類別與繼承的區別:
類別一般不能擴展類的屬性
不改變原類的條件下,想類添加方法
類別可以把相關的方法分組到多個單獨的文件中,便于管理
·類別與擴展的區別:
類別中原則上只能增加方法
擴展不僅可以增加方法,還可以增加屬性;
擴展中聲明的方法沒被實現,編譯器會報警;
擴展沒有獨立的實現部分,實現需在原類的.m文件中;且必須寫在@implementation的上方
擴展添加的屬性和方法屬于私有屬性和方法;
擴展只能針對自定義的類,不能給系統類增加類擴展
三、內存管理
基本數據類型的數據 內存在棧上,棧內存由系統去開辟和回收,對象類型的數據 內存在堆上,內存管理就是對對象的內存管理、對堆內存的管理(系統中有一個管理系統空閑空間的鏈表存放著空閑狀態的內存,申請內存時 系統會遍歷鏈表找到大于等于申請的內存的結點將該結點分配給發起申請的對象,并將該結點從存儲空閑內存空間的鏈表中移除;釋放一個對象時,對象占的內存回到空閑狀態系統又會將對象的堆結點存入鏈表中,等待下一次分配)
·iOS內存管理:對象通過引用計數來進行內存管理,引用計數記錄對象被幾個指針引用。引用計數為零時對象就會被銷毀。
·內存管理原則:誰創建,誰釋放,誰引用,誰管理
·內存管理方式:ARC、MRC、autorelease(自動釋放池)
·引用計數:繼承NSObject的類都有一個引用計數器retainCount,用于記錄當前被幾個指針引用,引用計數為零時對象就會被銷毀。
·autorelease:延遲釋放,調用autorelease對象的retainCount 不會立刻減1,而是被添加到自動釋放池管理延遲釋放對象的數組,等待自動釋放池執行結束時才會真正的釋放 retainCount - 1
mrc:
-(void)setName:(NSString *)name {
if(_name){
[_name release]; //-1
}
_name = [name retain]; //+1
}
id obj = [[NSObject alloc]init];//獲取引用計數
printf(“retain count = %ld\n”,CFGetRetainCount((__bridge CFTypeRef)(obj)));
·類方法創建的對象不需要手動release,原因是在類方法中添加了autorelease。缺點:不知道對象什么時候被釋放,可能造成提前釋放
·向數組/字典中添加對象時 對象的retainCount會加一,從數組/字典中移出對象,對象的retainCount會減一
Objective-C語言本身是支持垃圾回收機制的,但有平臺局限性,僅限于Mac桌面系統開發中
四、設計模式
MVC、MVVM、單例、代理(@required、@optional)、工廠、觀察者
·單例的寫法
單例指的是某個類的對象,在整個程序運行期間,只被創建一次,并且在整個程序運行期間都不會被銷毀,使用單例的優點:不用多次創建對象、整個工程都可以訪問這個對象的數據,實現數據共享
缺點:單例對象在程序運行期間都不會被銷毀,很多時候都占用內存,內存泄露問題(在工程中謹慎使用單例模式)
static Person * p = nil;
@implementation Person
//OC中最簡單的單例實現方式,但是并不推薦這樣去寫,多線程環境下,這樣是不能保證線程安全
+(instancetype)sharePerson{
}
+(instancetype)defaultPerson{
//使用關鍵字對對象加鎖,保證線程安全,這是蘋果推薦的單例實現方法之一
@synchronized (p) {
if(p == nil){
p = [[Person alloc]init];
}
}
return p;
}
+(instancetype)currentPerson{
//采用GCD dispatch_once 保證創建對象的代碼在整個程序運行期間只被執行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if(p == nil){
p = [[Person alloc]init];
}
});
return p;
}
·MVC設計模式的缺點:
厚重的ViewController
遺失的網絡邏輯(無立足之地)
較差的可測試性
· MVVM
MVVM將?Controller?中的展示邏輯抽取出來,放置到一個專門的地方,而這個地方就是?viewModel?。MVVM衍生于MVC,是對?MVC?的一種演進,它促進了 UI 代碼與業務邏輯的分離。它正式規范了視圖和控制器緊耦合的性質,并引入新的組件。
view?和?view controller正式聯系在一起,我們把它們視為一個組件
view?和?view controller?都不能直接引用model,而是引用視圖模型(viewModel)
viewModel?是一個放置用戶輸入驗證邏輯,視圖顯示邏輯,發起網絡請求和其他代碼的地方
使用MVVM會輕微的增加代碼量,但總體上減少了代碼的復雜性
·MVVM 的優點
低耦合:View?可以獨立于Model變化和修改,一個?viewModel?可以綁定到不同的?View?上
可重用性:可以把一些視圖邏輯放在一個?viewModel里面,讓很多?view?重用這段視圖邏輯
獨立開發:開發人員可以專注于業務邏輯和數據的開發?viewModel,設計人員可以專注于頁面設計
可測試:通常界面是比較難于測試的,而?MVVM?模式可以針對?viewModel來進行測試
·MVVM 的缺點
數據綁定使得Bug?很難被調試。你看到界面異常了,有可能是你?View?的代碼有?Bug,也可能是?Model?的代碼有問題。
對于過大的項目,數據綁定和數據轉化需要花費更多的內存(成本)。
·觀察者模式
觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。
觀察者模式的實現有兩種方法:Notification、KVO。
·工廠模式
工廠模式也稱為虛構造器,它適用于:一個類無法預期生成那個類對象,想讓其子類來指定所生成具體對象。
類有一組子類,可以共用一套接口,但是實例化的方式略有差異。用工廠的方式實現,使得客戶端(類的調用著)能夠專注于接口。而不需要訪問具體的實現類。
·何時使用工廠模式
編譯時無法確定預期要創建的對象類
類想讓子類決定運行時創建什么
·實現:抽象基類或協議。
五、runtime
1>OC 是一個全動態語言,OC 的一切都是基于 Runtime 實現的
平時編寫的OC代碼, 在程序運行過程中, 其實最終都是轉成了runtime的C語言代碼, runtime算是OC的幕后工作者
2>runtime是一套比較底層的純C語言API, 屬于1個C語言庫, 包含了很多底層的C語言API
3>runtimeAPI的實現是用 C++ 開發的(源碼中的實現文件都是mm),是一套蘋果開源的框架
OC在編譯的時候并不知道要調用哪個方法函數,只有在運行的時候才知道調用的方法函數名稱,來找到對應的方法函數進行調用。
·runtime的作用:(https://www.cnblogs.com/allencelee/p/7573627.html)
發送消息、交換方法、分類添加屬性、動態添加方法、字典轉模型KVC實現
·動態添加方法的實現:
SEL?sel?=?@selector?(start:)?;?//?指定action??
if?([obj?respondsToSelector:sel])?
{?//判斷該對象是否有相應的方法 ?
[obj?performSelector:sel?withObject:self];?//調用選擇器方法 ?
}
// 默認方法都有兩個隱式參數,
void eat(id self,SEL sel)
// 當一個對象調用未實現的方法,會調用這個方法處理,并且會把對應的方法列表傳過來.
+ (BOOL)resolveInstanceMethod:(SEL)sel
六、runloop 運行回路
·工作模式:NSDefaultRunLoopMode UITrackingRunLoopMode NSRunLoopCommonModes
優先處理UI模式的事件,再處理Default模式,Common為前兩者的集合
一般來講,一個線程一次只能執行一個任務,執行完成后線程就會退出。如果我們需要一個機制,讓線程能隨時處理事件但并不退出
七、網絡
·TCP和UDP的區別:
TCP可靠,穩定,慢,效率低,占用系統資源高,易被攻擊
(交換數據前,必須先在雙方之間建立一個TCP連接)三次握手 四次揮手
UDP快,比TCP稍安全,不可靠,不穩定
套接字(Socket)是通信的基石,是支持TCP/IP協議的網絡通信的基本操作單元
HTTP請求包由三個部分構成,分別是:請求方法-URI-協議/版本,請求頭,請求正文。
HTTP響應包由三個部分構成,分別是:協議-狀態代碼-描述,應答頭,應答正文。
·MD5加密的特點:
不可逆、長度固定、容易計算、抗修改性、安全
八、其他
在非ARC工程中采用ARC去編譯某些類:-fobjc-arc。
在ARC下的工程采用非ARC去編譯某些類:-fno-fobjc-arc
·NSObject內省方法:
1、isKindOfClass:Class
檢查對象是否是那個類或者其繼承類實例化的對象
2、isMemberOfClass:Class
檢查對象是否是那個類但不包括繼承類而實例化的對象
3、respondToSelector:selector
檢查對象是否包含這個方法
4、conformsToProtocol:protocol
檢查對象是否符合協議,是否實現了協議中所有的必選方法。
·事件傳遞響應鏈
系統會將事件加入到UIApplication管理的一個任務隊列中,以棧的形式存儲,先進先出先執行。
UIApplication會將事件發送給我們最底層的窗口UIWindow,這里的UIWindow值的是keyWindow(主),也只有顯示在keyWindow上的視圖才能接受點擊事件的響應。
UIWindow將事件發送給控制器(或者視圖),如果控制器能處理事件的響應,而且觸摸點在自己的身上,那么繼續尋找子視圖。
遍歷所有的子視圖,重復上一步的判斷,以此循環,直到條件不滿足。
(- 如果找到的作用點在子視圖上,但是子視圖的userInteractionEnabled屬性設置NO(是否響應的設置),那么這個事件就會被廢棄。 - 如果找不到觸摸點沒有在點擊的子視圖上,那么這個事件由父視圖執行。 - 如果摸點在子視圖的區域,但是設置了隱藏或者透明度為0時,那這個事件同樣由父視圖執行。)
//對象的生命周期:對象的生命周期從 alloc 開始,到delloc結束
loadView—viewDidLoad—drawRect—viewWillApper—viewDidAppear—viewWillDisAppear
//iOS 中的四個基本框架:Foundation、SystemConfiguration、UIKit、CFNetWork
Cocoa是OS X和 iOS操作系統的程序的運行環境。
Cocoa眾多框架中最重要最基本的兩個框架是:Foundation 和 UIKit。
Cocoa中的NSRunLoop類并不是線程安全的
總結
以上是生活随笔為你收集整理的OC基础知识(面试必看)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python使用pyhive库远程操作h
- 下一篇: 连续状态空间模型离散化