前兩天的直播: 孫源的面試小灶直播- 簡(jiǎn)歷、面試題绍载、進(jìn)階,今天回看悟狱,特此筆記下此蜈。
話(huà)說(shuō)那個(gè)經(jīng)典的 招聘一個(gè)靠譜的 iOS 的面試題 就是孫源出的。
直播中的要點(diǎn):
- 1袄秩、面試中的一些問(wèn)題
- 2茶凳、印象比較深的兩個(gè)題,特別是第二個(gè)
- 3播揪、iOS進(jìn)階的話(huà)題
1贮喧、面試中的一些問(wèn)題
- 注意最近一個(gè)工作經(jīng)歷(最重視,盡量詳細(xì))
- 細(xì)節(jié)問(wèn)題:
大小寫(xiě)猪狈、空格之類(lèi)的箱沦,說(shuō)明的就是標(biāo)準(zhǔn)式,可用 MarkDown - 可以提供更多的信息來(lái)體現(xiàn)你的特別
github雇庙、blog 的展示 - 專(zhuān)業(yè)技能: 到底用這個(gè)做過(guò)什么谓形?(例如 runtime 具體做過(guò)什么,Category 添加屬性疆前?替換方法寒跳?)
- 項(xiàng)目經(jīng)驗(yàn): 也是盡量詳細(xì), 可多描述下,自己所處團(tuán)隊(duì)中的位置竹椒,自己做了一些什么 模塊童太。
另外面試中, 要注意溝通的流暢性胸完,不知道的也可以試探性回答书释,甚至請(qǐng)教;不要老久不說(shuō)話(huà)赊窥,也不要裝 X爆惧,更不要造假 。
2锨能、印象比較深的兩個(gè)題扯再,特別是第二個(gè)
2-1芍耘、 array0 為什么有問(wèn)題?
- array0 也是有問(wèn)題的熄阻,當(dāng)外面?zhèn)魅胍粋€(gè)NSMutableArray的時(shí)候斋竞,會(huì)產(chǎn)生一些不必要的麻煩
- array1 和 array2 是正常的
- array3 是有問(wèn)題的,copy 后會(huì)讓 array3 從NSMutableArray 變成 NSArray ,后期假如使用 插入饺律、刪除之類(lèi)的方法時(shí)窃页,就會(huì)出現(xiàn) Crash 的跺株。
此處我的疑惑是 array0 ,因?yàn)槲乙话憔褪沁@樣寫(xiě)的复濒,雖說(shuō)傳 NSMutableArray 的時(shí)候,我一般會(huì) mutableArray.copy 的乒省,但是偶爾也有沒(méi)傳的時(shí)候巧颈,但是沒(méi)有出問(wèn)題啊袖扛? 這個(gè)一下子沒(méi)有想到例子...
后來(lái)再次看那經(jīng)典的面試題: 【招聘一個(gè)靠譜的 iOS 參考答案(上)】才重新理解了(它里面那個(gè)例子錯(cuò)了砸泛,可能手誤)。
NSArray *array = @[@1, @2, @3, @4];
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];
self.array0 = mutableArray;
[mutableArray removeAllObjects];;
NSLog(@"array0 == %@",self.array0);
array0
打印出來(lái)就是空的蛆封,像上面中當(dāng)我們使用是strong
,那么這個(gè)array0
就指向一個(gè)可變對(duì)象, 如果這個(gè)可變對(duì)象在外部被修改了唇礁,那么會(huì)影響該屬性。
父類(lèi)指針可以指向子類(lèi)對(duì)象惨篱,使用copy
的目的是為了讓本對(duì)象的屬性不受外界影響,使用copy
無(wú)論給我傳入是一個(gè)可變對(duì)象還是不可對(duì)象,我本身持有的就是一個(gè)不可變的副本盏筐。
2-2、 Block 的瞬間執(zhí)行
例如為什么 在下面的方法中砸讳,self 不需要寫(xiě) __weak
和__strong
琢融?
[UIView animateWithDuration:1.0f animations:^{
self.view.alpha = 0.5f;
}];
因?yàn)樗撬查g執(zhí)行的,這個(gè) UIView animationPush 之后簿寂,馬上就執(zhí)行了漾抬,所以這個(gè) Block 里面不會(huì)持有這個(gè) self,所以就不會(huì)造成循環(huán)引用啦常遂,所以就不需要寫(xiě)啦纳令。
對(duì)于這個(gè)問(wèn)題,Sunny 給出了七種方法...
- 1克胳、借助他人泊碑, 傳入Block ,立即執(zhí)行掉
- (void)blcokProblemAnswerOne:(void(^)(void))block {
// 讓他人幫我們調(diào)用
// 立即調(diào)用
[UIView animateWithDuration:0 animations:block];
// Or GCD
dispatch_async(dispatch_get_main_queue(), block);
}
- 2毯欣、 也是借助他人馒过,傳入Block ,手動(dòng)讓其銷(xiāo)毀
- (void)blcokProblemAnswerTwo:(void(^)(void))block {
[[NSBlockOperation blockOperationWithBlock:block] start];
}
- 3酗钞、NSInvocation 這個(gè)類(lèi)動(dòng)態(tài)實(shí)行方法
- (void)blcokProblemAnswerThree:(void(^)(void))block {
[[NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:"v@?"]]invokeWithTarget:block];
// v@? 需要詳細(xì)了解下
}
順便看看 動(dòng)態(tài)組一個(gè) OC 方法的調(diào)用
- (void)testUserInvacation {
NSMethodSignature *singnature = [self methodSignatureForSelector:@selector(description)];
NSInvocation *invacation = [NSInvocation invocationWithMethodSignature:singnature];
invacation.target = self;
invacation.selector = @selector(description);
[invacation invoke];
}
- 4腹忽、內(nèi)部 NSBlock 的方法来累,這是隱式的API
// 此處推薦了 一個(gè)工具 DLIntrospection
- (void)blcokProblemAnswerFour:(void(^)(void))block {
[block invoke];
}
- 5、 通過(guò)Blcok 內(nèi)存的結(jié)構(gòu)來(lái)處理
// 需要對(duì)指針窘奏、地址很熟悉
- (void)blcokProblemAnswerFive:(void(^)(void))block {
/**
struct Block_layout {
void *isa; // 指針
int flags; // 什么類(lèi)型 (int32_t)
int reserved; // int32_t
void (*invoke)(void *, ...); // C 函數(shù)的指針嘹锁,真正的調(diào)用
struct Block_descriptor *descriptor;
// Imported variables.
};
*/
// 目的是找到 void (*invoke)(void *, ...) 這個(gè)方法
// 實(shí)際上就是 首地址 看偏移多少,前面總共 16 (isa== 8, flag == 4, reservaed == 4)
void *pBlcok = (__bridge void *)block;
// 這個(gè) 加 2着裹, 领猾?骇扇?摔竿?
void (*invoke)(void *, ...) = *((void **)pBlcok + 2);
invoke(pBlcok); // 傳第一個(gè)參數(shù)
}
- 6、利用 Clang 中一些節(jié)點(diǎn)少孝,完全懵的
static void blcokCleanUp(__strong void(^*block)(void)) {
(*block)();
}
- (void)blcokProblemAnswerSix:(void(^)(void))block {
__strong void(^cleaner)(void) __attribute ((cleanup(blcokCleanUp),unused)) = block;
}
- 7继低、內(nèi)聯(lián)一個(gè)匯編 完成調(diào)用,完全醉了
- (void)blcokProblemAnswerSeven:(void(^)(void))block {
// block(); // dis 找到其 方法的來(lái)源
asm("callq *0x10(%rax)");
}
這真的是大開(kāi)眼界啊稍走,個(gè)人第一種和第二種還能接受袁翁,第三種和第五種是想要掌握,其他的還是看看吧婿脸,確實(shí)是漲知識(shí)啦A皇ぁ!狐树!像 NSInvocation 就得立馬去補(bǔ)補(bǔ)啦焙压!
PS1: class 關(guān)鍵詞用于 property 的新特征 , 表示類(lèi)的屬性,和 Swift 橋接的褪迟。
@interface TestObject : NSObject
@property (nonatomic, class) TestObject *shareObject; // 盡量讓其訪(fǎng)問(wèn)權(quán)限最小
@end
可以更好的寫(xiě)單例
// 寫(xiě)單例冗恨,都可以直接, 這樣寫(xiě)啦
+ (TestObject *) shareObject {
}
PS2: DLIntrospection 一個(gè)很贊的工具
可以獲取 NSObject 的 屬性味赃、方法掀抹、繼承結(jié)構(gòu)之類(lèi)的 ,看Sunny 用的很爽心俗。
3傲武、iOS進(jìn)階的話(huà)題
單靠知識(shí)點(diǎn)累計(jì)還不行,需要有自己的思考城榛,對(duì)技術(shù)的主見(jiàn)
將各個(gè)知識(shí)點(diǎn)串聯(lián)起來(lái)形成自己的東東揪利。
對(duì)于我個(gè)人來(lái)說(shuō),對(duì)我很有啟發(fā)的是:
- 寫(xiě)文章可以用點(diǎn)代替面狠持,注意積累
- 丁字領(lǐng)域說(shuō)法不錯(cuò)疟位,發(fā)展一門(mén)深的,其他的都融會(huì)貫通啦
- 對(duì)于知識(shí)點(diǎn)的深挖喘垂,挖到自己不能再挖為止甜刻,后期還得經(jīng)常反思绍撞、串聯(lián),然后形成自己體系得院。
而我最大的問(wèn)題傻铣,就是每次淺嘗即止,沒(méi)能刨根問(wèn)底祥绞!
另外Sunny 的說(shuō):寫(xiě)博客就要寫(xiě)別人沒(méi)寫(xiě)過(guò)的非洲,我想對(duì)于我來(lái)說(shuō)是有待商榷的,個(gè)人應(yīng)該是說(shuō)寫(xiě)博客要追求別人沒(méi)寫(xiě)過(guò)的蜕径!畢竟目前還是以記筆記為主两踏,希望得先積累多一些點(diǎn)吧!
最后丧荐,Sunny 為大家?guī)?lái)了福利缆瓣,之前的視頻下載地址喧枷,包括 他之前 Clang 和 RunLoop 的視頻,虹统,非常贊,也非常感謝隧甚!