1、UIView 和 CALayer 的區(qū)別
1. UIView可以響應(yīng)事件,Layer不可以,因?yàn)閁IView繼承自UIResponder類,而 CALayer直接繼承 NSObject
2. UIView自身不能設(shè)置圓角等效果, 而CALayer可設(shè)置邊框, 圓角, 陰影和變換變形等
3. UIView主要是對(duì)顯示內(nèi)容的管理, 而CALayer主要是顯示內(nèi)容的繪制
4. CALayer默認(rèn)修改屬性支持隱式動(dòng)畫(huà)
2、RunLoop和多線程的關(guān)系
1. 每條線程都有唯一的一個(gè) RunLoop 對(duì)象與之對(duì)應(yīng)的
2. 主線程的 RunLoop 是自動(dòng)創(chuàng)建并啟動(dòng),UIApplicationMain()函數(shù),這個(gè)方法會(huì)為main thread設(shè)置一個(gè)NSRunLoop對(duì)象。
這就解釋了:為什么我們的應(yīng)用可以在無(wú)人操作的時(shí)候休息,需要讓它干活的時(shí)候又能立馬響應(yīng)。
3. 子線程的 RunLoop 需要手動(dòng)創(chuàng)建,run loop默認(rèn)是沒(méi)有啟動(dòng)的,如果你需要更多的線程交互則可以手動(dòng)配置和啟動(dòng)
4. 在任何一個(gè) Cocoa 程序的線程中,都可以通過(guò)以下代碼來(lái)獲取到當(dāng)前線程的 run loop 。
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
3、__block 和 __weak 的區(qū)別
1. __weak 本身是可以避免循環(huán)引用的問(wèn)題的,但是其會(huì)導(dǎo)致外部對(duì)象釋放了之后,block 內(nèi)部也訪問(wèn)不到這個(gè)對(duì)象的問(wèn)題,
我們可以通過(guò)在 block 內(nèi)部聲明一個(gè) __strong 的變量來(lái)指向 weakObj,使外部對(duì)象既能在 block 內(nèi)部保持住,又能避免循環(huán)引用的問(wèn)題。
2. __block 本身無(wú)法避免循環(huán)引用的問(wèn)題,但是我們可以通過(guò)在 block 內(nèi)部手動(dòng)把 blockObj 賦值為 nil 的方式來(lái)避免循環(huán)引用的問(wèn)題。
3. __block 修飾的變量在 block 內(nèi)外都是唯一的,要注意這個(gè)特性可能帶來(lái)的隱患。
4. __block在ARC環(huán)境下,無(wú)法避免循環(huán)引用的問(wèn)題。在非arc下,__block是可以避免引用循環(huán)的
4、Runtime 怎樣實(shí)現(xiàn) weak 屬性的
通過(guò)關(guān)聯(lián)屬性來(lái)實(shí)現(xiàn)
//聲明一個(gè)weak屬性,以delegate為例
@property (nonatomic, weak) id delegate;
//重寫(xiě)getter、setter方法
- (id)delegate {
return objc_getAssociatedObject(self, @"__delegate__key");
}
//指定使用OBJC_ASSOCIATION_ASSIGN
- (void)setDelegate:(id)delegate {
objc_setAssociatedObject(self, @"__delegate__key", delegate, OBJC_ASSOCIATION_ASSIGN);
}
5、筆試題:
寫(xiě)出打印結(jié)果,并說(shuō)明為什么
//全民快樂(lè)筆試題
- (void)gcdTest {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"4");
});
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"5");
});
[self performSelector:@selector(test2)];
[self performSelector:@selector(test3) withObject:nil afterDelay:0];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"6");
});
[self test1];
}
- (void)test1 {
NSLog(@"1");
}
- (void)test2 {
NSLog(@"2");
}
- (void)test3 {
NSLog(@"3");
}
(!!!!運(yùn)行結(jié)果是:216453 )
# 解決思路
1. 搞清楚下面兩者區(qū)別
dispatch_async
dispatch_sync
2.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"4");
});
等價(jià)于
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"4");
});
3. [self performSelector:@selector(test2)];
等價(jià)于
[self test2];
4.
[self performSelector:@selector(test3) withObject:nil afterDelay:0];
等價(jià)于
dispatch_async(dispatch_get_main_queue(), ^{
[self test3];
});
5. 要知道在主線程上運(yùn)行以下兩句話, 這里查文檔好好理解一下吧
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"A");
});
NSLog(@"B");
打印結(jié)果是 BA
6.
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"6");
});
這個(gè)數(shù)字出現(xiàn)比較隨機(jī),所以不用太在意
所以上面代碼簡(jiǎn)化為,(忽略6)
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"4");
});
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"5");
});
[self test2];
dispatch_async(dispatch_get_main_queue(), ^{
[self test3];
});
[self test1];
結(jié)果: 21453 (6出現(xiàn)的位置比較隨機(jī))