7月,iOS求職跳槽的相對較少骡尽,能在這個時間段求職的遣妥,
不是被迫,就是對自己的技術(shù)很自信攀细;
針對7月箫踩,特別總結(jié)了一份iOS常見大廠面試題(上);
iOS面試題分為 上、中谭贪、下三部分境钟,方便大家觀看;
請先自己答一答
!
話不多說俭识;直接上題
本文收錄:公眾號【iOS進階寶典《iOS底層面試題(上篇)》】
1:談?wù)勀銓VC的理解
KVC
可以通過key
直接訪問對象的屬性慨削,或者給對象的屬性賦值,這樣可以在運行時動態(tài)的訪問或修改對象的屬性
2:iOS項目中引用多個第三方庫引發(fā)沖突的解決方法
可能有很多小伙伴還不太清楚,動靜態(tài)庫的開發(fā)理盆,這里推薦一篇博客:iOS-制作.a靜態(tài)庫SDK和使用.a靜態(tài)庫
如果我們存在三方庫沖突就會保存:duplicate symbol _OBJC_IVAR_$_xxxx in:
目前見效最快的就是把**.framework**
選中痘煤,**taggert Membership**
的對勾取消掉,就編譯沒有問題了猿规,但是后續(xù)的其他問題可能還會出現(xiàn)
我想說的是像這種開源的使用率很高的源代碼本不應該包含在lib庫中衷快,就算是你要包含那也要改個名字是吧。不過沒辦法現(xiàn)在人家既然包含姨俩,我們就只有想辦法分離了
mkdir armv7:創(chuàng)建臨時文件夾
lipo libALMovie.a -thin armv7 -output armv7/armv7.a:取出armv7平臺的包
ar -t armv7/armv7.a:查看庫中所包含的文件列表
cd armv7 && ar xv armv7.a:解壓出object file(即.o后綴文件)
rm ALButton.o:找到?jīng)_突的包蘸拔,刪除掉(此步可以多次操作)
cd … && ar rcs armv7.a armv7/*.o:重新打包object file
多平臺的SDK的話,需要多次操作第4步环葵。
操作完成后调窍,合并多個平臺的文件為一個.a文件:
lipo -create armv7.a arm64.a -output new.a
將修改好的文件, 拖拽到原文件夾下张遭,替換原文件即可邓萨。
3:GCD實現(xiàn)多讀單寫
比如在內(nèi)存中維護一份數(shù)據(jù),有多處地方可能會同時操作這塊數(shù)據(jù)菊卷,怎么能保證數(shù)據(jù)安全缔恳?
這道題目總結(jié)得到要滿足以下三點:
- 1.讀寫互斥
- 2.寫寫互斥
- 3.讀讀并發(fā)
@implementation KCPerson
- (instancetype)init
{
if (self = [super init]) {
_concurrentQueue = dispatch_queue_create("com.kc_person.syncQueue", DISPATCH_QUEUE_CONCURRENT);
_dic = [NSMutableDictionary dictionary];
}
return self;
}
- (void)kc_setSafeObject:(id)object forKey:(NSString *)key{
key = [key copy];
dispatch_barrier_async(_concurrentQueue, ^{
[_dic setObject:object key:key];
});
}
- (id)kc_safeObjectForKey::(NSString *)key{
__block NSString *temp;
dispatch_sync(_concurrentQueue, ^{
temp =[_dic objectForKey:key];
});
return temp;
}
@end
首先我們要維系一個GCD 隊列,最好不用全局隊列洁闰,畢竟大家都知道全局隊列遇到柵欄函數(shù)是有坑點的歉甚,這里就不分析了!
因為考慮性能 死鎖 堵塞的因素不考慮串行隊列扑眉,用的是自定義的并發(fā)隊列纸泄!
_concurrentQueue = dispatch_queue_create("com.kc_person.syncQueue", DISPATCH_QUEUE_CONCURRENT);
首先我們來看看讀操作:
kc_safeObjectForKey
我們考慮到多線程影響是不能用異步函數(shù)的!說明:線程2 獲妊亍:
name
線程3 獲取age
如果因為異步并發(fā)聘裁,導致混亂 本來讀的是
name
結(jié)果讀到了age
我們允許多個任務(wù)同時進去! 但是讀操作需要同步返回,所以我們選擇:
同步函數(shù)
(讀讀并發(fā))我們再來看看寫操作耸弄,在寫操作的時候?qū)ey進行了copy, 關(guān)于此處的解釋咧虎,插入一段來自參考文獻的引用:
函數(shù)調(diào)用者可以自由傳遞一個
NSMutableString
的key
,并且能夠在函數(shù)返回后修改它计呈。因此我們必須對傳入的字符串使用copy
操作以確保函數(shù)能夠正確地工作砰诵。如果傳入的字符串不是可變的(也就是正常的NSString
類型),調(diào)用copy
基本上是個空操作捌显。
這里我們選擇
dispatch_barrier_async
, 為什么是柵欄函數(shù)而不是異步函數(shù)或者同步函數(shù)茁彭,下面分析:柵欄函數(shù)任務(wù):之前所有的任務(wù)執(zhí)行完畢,并且在它后面的任務(wù)開始之前扶歪,期間不會有其他的任務(wù)執(zhí)行理肺,這樣比較好的促使 寫操作一個接一個寫 (寫寫互斥)摄闸,不會亂!
為什么不是異步函數(shù)妹萨?應該很容易分析年枕,畢竟會產(chǎn)生混亂!
為什么不用同步函數(shù)乎完?如果讀寫都操作了熏兄,那么用同步函數(shù),就有可能存在:我寫需要等待讀操作回來才能執(zhí)行树姨,顯然這里是不合理摩桶!
4:講一下atomic的實現(xiàn)機制;為什么不能保證絕對的線程安全(最好可以結(jié)合場景來說)帽揪?
A: atomic的實現(xiàn)機制
atomic
是property
的修飾詞之一硝清,表示是原子性的,使用方式為@property(atomic)int age
;此時編譯器會自動生成getter/setter
方法转晰,最終會調(diào)用objc_getProperty
和objc_setProperty
方法來進行存取屬性芦拿。若此時屬性用
atomic
修飾的話,在這兩個方法內(nèi)部使用os_unfair_lock
來進行加鎖挽霉,來保證讀寫的原子性防嗡。鎖都在PropertyLocks
中保存著(在iOS平臺會初始化8個变汪,mac平臺64個)侠坎,在用之前,會把鎖都初始化好裙盾,在需要用到時实胸,用對象的地址加上成員變量的偏移量為key
,去PropertyLocks
中去取番官。因此存取時用的是同一個鎖庐完,所以atomic能保證屬性的存取時是線程安全的。注:由于鎖是有限的徘熔,不用對象门躯,不同屬性的讀取用的也可能是同一個鎖
B: atomic為什么不能保證絕對的線程安全?
atomic
在getter/setter
方法中加鎖酷师,僅保證了存取時的線程安全讶凉,假設(shè)我們的屬性是@property(atomic)NSMutableArray *array
;可變的容器時,無法保證對容器的修改是線程安全的.- 在編譯器自動生產(chǎn)的
getter/setter
方法,最終會調(diào)用objc_getProperty
和objc_setProperty
方法存取屬性山孔,在此方法內(nèi)部保證了讀寫時的線程安全的懂讯,當我們重寫getter/setter
方法時,就只能依靠自己在getter/setter
中保證線程安全
5. Autoreleasepool所使用的數(shù)據(jù)結(jié)構(gòu)是什么台颠?AutoreleasePoolPage結(jié)構(gòu)體了解么褐望?
Autoreleasepool
是由多個AutoreleasePoolPage
以雙向鏈表的形式連接起來的.Autoreleasepool
的基本原理:在每個自動釋放池創(chuàng)建的時候,會在當前的AutoreleasePoolPage
中設(shè)置一個標記位,在此期間瘫里,當有對象調(diào)用autorelsease
時实蔽,會把對象添加AutoreleasePoolPage
中若當前頁添加滿了,會初始化一個新頁谨读,然后用雙向量表鏈接起來盐须,并把新初始化的這一頁設(shè)置為
hotPage
,當自動釋放池pop時,從最下面依次往上pop漆腌,調(diào)用每個對象的release
方法贼邓,直到遇到標志位。
AutoreleasePoolPage
結(jié)構(gòu)如下
class AutoreleasePoolPage {
magic_t const magic;
id *next;//下一個存放autorelease對象的地址
pthread_t const thread; //AutoreleasePoolPage 所在的線程
AutoreleasePoolPage * const parent;//父節(jié)點
AutoreleasePoolPage *child;//子節(jié)點
uint32_t const depth;//深度,也可以理解為當前page在鏈表中的位置
uint32_t hiwat;
}
文末推薦:iOS熱門文集
① Swift
② iOS底層技術(shù)
③ iOS逆向防護
④ iOS面試合集
喜歡的小伙伴記得點贊喔~
收藏等于白嫖闷尿,點贊才是真情?( ′???` )?