iOS 進(jìn)階+面試(三)

本篇文章是承接上篇文章 iOS 進(jìn)階+面試(二)

二十一、可變數(shù)組與不可變數(shù)組用什么修飾:原因?

地址http://www.lxweimin.com/p/27305b08b0f2

二十二、nsstring 使用什么關(guān)鍵字修飾?

地址http://www.lxweimin.com/p/9b77d61d76fe

二十三、線上項(xiàng)目崩潰,日志處理?

友盟, 集成需要在

-(void)viewWillAppear:(BOOL)animated
-(void)viewWillDisappear:(BOOL)animated
2368070-db2e7b98f2ef9589.png

詳解 : 用友盟詳細(xì)說明一下

  • 報(bào)表中心中下載錯(cuò)誤
  • 友盟Crash分析工具與下載的錯(cuò)誤報(bào)表放同一文件夾中, 打開 終端 , 先拖入友盟Crash分析工具** 再拖入 錯(cuò)誤報(bào)表 , 按回車
  1. 進(jìn)入友盟 個(gè)人中心 -> 錯(cuò)誤分析 -> 錯(cuò)誤列表 -> 點(diǎn)擊列表中錯(cuò)誤進(jìn)入界面
2368070-da6c7ccaf8c7757c.png

2. 點(diǎn)擊 右上角 進(jìn)入 [報(bào)表中心] 下載該錯(cuò)誤. 將 友盟Crash分析工具與下載的錯(cuò)誤報(bào)表放同一文件夾中, 打開 終端 , 先拖入友盟Crash分析工具 再拖入 錯(cuò)誤報(bào)表 , 按回車.

2368070-f9b083e8a22d57b7.png
  1. 終端 運(yùn)行完成后 , 會(huì)顯示錯(cuò)誤的位置與行數(shù)

二十四、談?wù)劧嗑€程的理解?

  • 使用線程可以把程序中占據(jù)時(shí)間長的任務(wù)放到后臺(tái)去處理,如圖片、視頻的下載
  • 充分利用系統(tǒng)的多核 發(fā)揮多核處理器的優(yōu)勢(shì),并發(fā)執(zhí)行讓系統(tǒng)運(yùn)行的更快、更流暢,用戶體驗(yàn)更好

缺點(diǎn):

  • 更多的線程需要更多的內(nèi)存空間

  • 當(dāng)多個(gè)線程對(duì)同一個(gè)資源出現(xiàn)爭(zhēng)奪的時(shí)候要注意線程安全的問題。

二十五、iPhone x max這個(gè)你們是怎樣適配的?

iOS11之前導(dǎo)航欄默認(rèn)高度為64pt(這里高度指statusBar + NavigationBar),iOS11之后如果設(shè)置了prefersLargeTitles = YES則為96pt,默認(rèn)情況下還是64pt,但在iPhoneX上由于劉海的出現(xiàn)statusBar由以前的20pt變成了44pt,所以iPhoneX上高度變?yōu)?8pt,如果項(xiàng)目里隱藏了導(dǎo)航欄加了自定義按鈕之類的,這里需要注意適配一下。

之前是按照定義宏變量適配的,這個(gè)感覺每次新出手機(jī)都要重新適配新手機(jī),iOS11 新出安全區(qū)域的概念,這是我們可以根據(jù)安全區(qū)域來適配,


2361189-9b6ed5e97f74d0c3.png

問題:

  • 導(dǎo)航欄圖層及對(duì)titleView布局的影響

iOS11之前導(dǎo)航欄的title是添加在UINavigationItemView上面,而navigationBarButton則直接添加在UINavigationBar上面,如果設(shè)置了titleView,則titleView也是直接添加在UINavigationBar上面。iOS11之后,大概因?yàn)閘argeTitle的原因,視圖層級(jí)發(fā)生了變化,如果沒有給titleView賦值,則titleView會(huì)直接添加在_UINavigationBarContentView上面,如果賦值了titleView,則會(huì)把titleView添加在_UITAMICAdaptorView上,而navigationBarButton被加在了_UIButtonBarStackView上,然后他們都被加在了_UINavigationBarContentView上,如圖:


20170926171451245.jpg

所以如果你的項(xiàng)目是自定義的navigationBar,那么在iOS11上運(yùn)行就可能出現(xiàn)布局錯(cuò)亂的bug,解決辦法是重寫UINavigationBar的layoutSubviews方法,調(diào)整布局,上代碼:

- (void)layoutSubviews {
  [super layoutSubviews];
  //注意導(dǎo)航欄及狀態(tài)欄高度適配
  self.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), naviBarHeight);
  for (UIView *view in self.subviews) {
    if([NSStringFromClass([view class]) containsString:@"Background"]) {
      view.frame = self.bounds;
    }
    else if ([NSStringFromClass([view class]) containsString:@"ContentView"]) {
      CGRect frame = view.frame;
      frame.origin.y = statusBarHeight;
      frame.size.height = self.bounds.size.height - frame.origin.y;
      view.frame = frame;
    }
  }
}
  • UIScrollView、UITableView、UICollectionView

大家在iOS11設(shè)備上運(yùn)行出現(xiàn)最多問題應(yīng)該就是tableview莫名奇妙的偏移20pt或者64pt了。。原因是iOS11棄用了automaticallyAdjustsScrollViewInsets屬性,取而代之的是UIScrollView新增了contentInsetAdjustmentBehavior屬性,這一切的罪魁禍?zhǔn)锥际切乱氲膕afeArea,關(guān)于safeArea適配這篇文章iOS 11 安全區(qū)域適配總結(jié)講的很詳細(xì),感興趣的可以看下,我直接貼適配代碼,因?yàn)榈桶姹局苯佑胏ontentInsetAdjustmentBehavior會(huì)報(bào)警告,所有定義了如下的宏(感謝@炒雞范的指正,之前的宏犯了個(gè)低級(jí)錯(cuò)誤...現(xiàn)改為)

#define adjustsScrollViewInsets(scrollView)\
do {\
_Pragma("clang diagnostic push")\
_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"")\
if ([scrollView respondsToSelector:NSSelectorFromString(@"setContentInsetAdjustmentBehavior:")]) {\
  NSMethodSignature *signature = [UIScrollView instanceMethodSignatureForSelector:@selector(setContentInsetAdjustmentBehavior:)];\
  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];\
  NSInteger argument = 2;\
  invocation.target = scrollView;\
  invocation.selector = @selector(setContentInsetAdjustmentBehavior:);\
  [invocation setArgument:&argument atIndex:2];\
  [invocation retainArguments];\
  [invocation invoke];\
}\
_Pragma("clang diagnostic pop")\
} 

還有的發(fā)現(xiàn)某些界面tableView的sectionHeader、sectionFooter高度與設(shè)置不符的問題,在iOS11中如果不實(shí)現(xiàn) -tableView: viewForHeaderInSection:和-tableView: viewForFooterInSection: ,則-tableView: heightForHeaderInSection:和- tableView: heightForFooterInSection:不會(huì)被調(diào)用,導(dǎo)致它們都變成了默認(rèn)高度,這是因?yàn)閠ableView在iOS11默認(rèn)使用Self-Sizing,tableView的estimatedRowHeight、estimatedSectionHeaderHeight、 estimatedSectionFooterHeight三個(gè)高度估算屬性由默認(rèn)的0變成了UITableViewAutomaticDimension,解決辦法簡(jiǎn)單粗暴,就是實(shí)現(xiàn)對(duì)應(yīng)方法或把這三個(gè)屬性設(shè)為0。
如果你使用了Masonry,那么你需要適配safeArea

if (@available(iOS 11.0, *)) {
  make.edges.equalTo()(self.view.safeAreaInsets)
} else {
  make.edges.equalTo()(self.view)
}
  • TabBarController

在viewWillAppear時(shí) tabbar高度是49(默認(rèn)高度?)
在viewDidAppear時(shí) tabbar高度是83(真實(shí)準(zhǔn)確高度)

可我在viewDidLoad時(shí)候就開始繪制界面了 如何適配?

具體的實(shí)現(xiàn)邏輯就是寫一個(gè)繼承UITabBarController的類然后修改類里面的方法

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    if (@available(iOS 11.0, *)){
        for (UIView *view in self.view.subviews) {
            if ([view isKindOfClass:[UITabBar class]]) {
            //x的位置不變 y的位置你自己調(diào)調(diào)到UI滿意 寬不變 高也不能變      最終只是改變一下y的相對(duì)位置
              view.frame = CGRectMake(view.frame.origin.x, self.view.bounds.size.height-64, view.frame.size.width, 83);
             }

        }
    
     }

}

之前這么寫有一個(gè)問題,就是會(huì)出現(xiàn)tabbar在push和pop的時(shí)候有上移下移的問題,后來查了一些資料解決了這個(gè)問題,在需要展示tabbar的控制器中添加下面的代碼就可以了

 - (void)viewWillDisappear:(BOOL)animated{
    if (iPhoneX) {
        if (@available(iOS 11.0, *)){
            // 修改tabBra的frame
            CGRect frame = self.tabBarController.tabBar.frame;
            frame.origin.y = [UIScreen mainScreen].bounds.size.height -64;
            self.navigationController.tabBarController.tabBar.frame = frame;
        }
        
    }
    
}
- (void)viewWillAppear:(BOOL)animated{
    if (iPhoneX) {
        if (@available(iOS 11.0, *)){
            // 修改tabBra的frame
            CGRect frame = self.tabBarController.tabBar.frame;
            frame.origin.y = [UIScreen mainScreen].bounds.size.height -64;
            self.navigationController.tabBarController.tabBar.frame = frame;
        }
        
    }
    
}

二十六、git的常見命令操作

git pull 拉下項(xiàng)目代碼

git status 查看狀態(tài)

git checkout --readme.txt 把readme.txt文件在工作去的修改全部撤銷

git rm 用于刪除一個(gè)文件

git branch dev 創(chuàng)建dev分支

git checkout dev 跳轉(zhuǎn)到dev分支 //注意當(dāng)前的要先提交然后再跳轉(zhuǎn)

git checkout -b dev 創(chuàng)建并切換到dev分支

git branch 查看當(dāng)前分支

二十七、http中的三次握手和四次揮手?

1:客戶端向服務(wù)器發(fā)出連接請(qǐng)求報(bào)文
2:TCP服務(wù)器收到請(qǐng)求報(bào)文后,如果同意連接,則發(fā)出確認(rèn)報(bào)文
3:TCP客戶進(jìn)程收到確認(rèn)后,還要向服務(wù)器給出確認(rèn)

思考:為什么要三次握手呢,有人說兩次握手就好了?
舉例:已失效的連接請(qǐng)求報(bào)文段。

client發(fā)送了第一個(gè)連接的請(qǐng)求報(bào)文,但是由于網(wǎng)絡(luò)不好,這個(gè)請(qǐng)求沒有立即到達(dá)服務(wù)端,而是在某個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)中滯留了,直到某個(gè)時(shí)間才到達(dá)server,本來這已經(jīng)是一個(gè)失效

的報(bào)文,但是server端接收到這個(gè)請(qǐng)求報(bào)文后,還是會(huì)想client發(fā)出確認(rèn)的報(bào)文,表示同意連接。假如不采用三次握手,那么只要server發(fā)出確認(rèn),新的建立就連接了,但其實(shí)這個(gè)

請(qǐng)求是失效的請(qǐng)求,client是不會(huì)理睬server的確認(rèn)信息,也不會(huì)向服務(wù)端發(fā)送確認(rèn)的請(qǐng)求,但是server認(rèn)為新的連接已經(jīng)建立起來了,并一直等待client發(fā)來數(shù)據(jù),這樣,server的

很多資源就沒白白浪費(fèi)掉了,采用三次握手就是為了防止這種情況的發(fā)生,server會(huì)因?yàn)槭詹坏酱_認(rèn)的報(bào)文,就知道client并沒有建立連接。這就是三次握手的作用。

  • TCP的四次揮手 ?
    1、TCP發(fā)送一個(gè)FIN(結(jié)束),用來關(guān)閉客戶到服務(wù)端的連接。
    2、服務(wù)端收到這個(gè)FIN,他發(fā)回一個(gè)ACK(確認(rèn)),確認(rèn)收到序號(hào)為收到序號(hào)+1,和SYN一樣,一個(gè)FIN將占用一個(gè)序號(hào)
    3、 服務(wù)端發(fā)送一個(gè)FIN(結(jié)束)到客戶端,服務(wù)端關(guān)閉客戶端的連接。
    4、客戶端發(fā)送ACK(確認(rèn))報(bào)文確認(rèn),并將確認(rèn)的序號(hào)+1,這樣關(guān)閉完成

思考:那么為什么是4次揮手呢?

為了確保數(shù)據(jù)能夠完成傳輸。

  關(guān)閉連接時(shí),當(dāng)收到對(duì)方的FIN報(bào)文通知時(shí),它僅僅表示對(duì)方?jīng)]有數(shù)據(jù)發(fā)送給你了;但未必你所有的數(shù)據(jù)都全部發(fā)送給對(duì)方了,所以你可以未必會(huì)馬上會(huì)關(guān)閉SOCKET,也

即你可能還需要發(fā)送一些數(shù)據(jù)給對(duì)方之后,再發(fā)送FIN報(bào)文給對(duì)方來表示你同意現(xiàn)在可以關(guān)閉連接了,所以它這里的ACK報(bào)文和FIN報(bào)文多數(shù)情況下都是分開發(fā)送的。

可能有人會(huì)有疑問,tcp我握手的時(shí)候?yàn)楹蜛CK(確認(rèn))和SYN(建立連接)是一起發(fā)送。揮手的時(shí)候?yàn)槭裁词欠珠_的時(shí)候發(fā)送呢 ????

因?yàn)楫?dāng)Server端收到Client端的SYN連接請(qǐng)求報(bào)文后,可以直接發(fā)送SYN+ACK報(bào)文。其中ACK報(bào)文是用來應(yīng)答的,

思考:客戶端突然掛掉了怎么辦?

正常連接時(shí),客戶端突然掛掉了,如果沒有措施處理這種情況,那么就會(huì)出現(xiàn)客戶端和服務(wù)器端出現(xiàn)長時(shí)期的空閑。解決辦法是在服務(wù)器端設(shè)置保活計(jì)時(shí)器,每當(dāng)服務(wù)器收到

客戶端的消息,就將計(jì)時(shí)器復(fù)位。超時(shí)時(shí)間通常設(shè)置為2小時(shí)。若服務(wù)器超過2小時(shí)沒收到客戶的信息,他就發(fā)送探測(cè)報(bào)文段。若發(fā)送了10個(gè)探測(cè)報(bào)文段,每一個(gè)相隔75秒,

還沒有響應(yīng)就認(rèn)為客戶端出了故障,因而終止該連接。

  • 四、TCP和UDP的區(qū)別

我這里簡(jiǎn)單列舉幾個(gè),因?yàn)槲疫€沒有研究UDP這個(gè)協(xié)議。

1、基于連接與無連接;UDP是無連接的,即發(fā)送數(shù)據(jù)之前不需要建立連接

2、TCP保證數(shù)據(jù)正確性,UDP可能丟包,TCP保證數(shù)據(jù)順序,UDP不保證。也就是說,通過TCP連接傳送的數(shù)據(jù),無差錯(cuò),不丟失,不重復(fù),且按序到達(dá);UDP盡最大努力交付

   ,即不保證可靠交付Tcp通過校驗(yàn)和,重傳控制,序號(hào)標(biāo)識(shí),滑動(dòng)窗口、確認(rèn)應(yīng)答實(shí)現(xiàn)可靠傳輸。如丟包時(shí)的重發(fā)控制,還可以對(duì)次序亂掉的分包進(jìn)行順序控制。

3、UDP具有較好的實(shí)時(shí)性,工作效率比TCP高,適用于對(duì)高速傳輸和實(shí)時(shí)性有較高的通信或廣播通信。

4、每一條TCP連接只能是點(diǎn)到點(diǎn)的;UDP支持一對(duì)一,一對(duì)多,多對(duì)一和多對(duì)多的交互通信。

5、TCP對(duì)系統(tǒng)資源要求較多,UDP對(duì)系統(tǒng)資源要求較少。

二十八、IOS 保證線程同步方式&性能對(duì)比

二十九、數(shù)據(jù)庫

文章 http://www.lxweimin.com/p/d8b980b41de4

三十、iOS中UITableViewCell的重用機(jī)制原理?

  • 重用實(shí)現(xiàn)分析

查看UITableView頭文件,會(huì)找到NSMutableArray* visiableCells,和NSMutableDictnery* reusableTableCells兩個(gè)結(jié)構(gòu)。visiableCells內(nèi)保存當(dāng)前顯示的cells,reusableTableCells保存可重 用的cells

TableView顯示之初,reusableTableCells為空,那么tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。開始的cell都是通過 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]來創(chuàng)建,而且cellForRowAtIndexPath只是調(diào)用最大顯示cell數(shù)的 次數(shù)

比如:有100條數(shù)據(jù),iPhone一屏最多顯示10個(gè)cell。程序最開始顯示TableView的情況是:

1. 用[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]創(chuàng)建10次cell,并給cell指定同樣的重用標(biāo)識(shí)(當(dāng)然,可以為不同顯示類型的 cell指定不同的標(biāo)識(shí))。并且10個(gè)cell全部都加入到visiableCells數(shù)組,reusableTableCells為空。

2. 向下拖動(dòng)tableView,當(dāng)cell1完全移出屏幕,并且cell11(它也是alloc出來的,原因同上)完全顯示出來的時(shí)候。cell11加入到 visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。

3. 接著向下拖動(dòng)tableView,因?yàn)閞eusableTableCells中已經(jīng)有值,所以,當(dāng)需要顯示新的 cell,cellForRowAtIndexPath再次被調(diào)用的時(shí)候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。cell1加入到 visiableCells,cell1移出reusableTableCells;cell2移出visiableCells,cell2加入到 reusableTableCells。之后再需要顯示的Cell就可以正常重用了。

所以整個(gè)過程并不難理解,但需要注意正是因?yàn)檫@樣的原因:配置Cell的時(shí)候一定要注意,對(duì)取出的重用的cell做重新賦值,不要遺留老數(shù)據(jù)

  • 一些情況

使用過程中,我注意到,并不是只有拖動(dòng)超出屏幕的時(shí)候才會(huì)更新reusableTableCells表,還有:

1. reloadData,這種情況比較特殊。一般是部分?jǐn)?shù)據(jù)發(fā)生變化,需要重新刷新cell顯示的內(nèi)容時(shí)調(diào)用。在 cellForRowAtIndexPath調(diào)用中,所有cell都是重用的。我估計(jì)reloadData調(diào)用后,把visiableCells中所有 cell移入reusableTableCells,visiableCells清空。cellForRowAtIndexPath調(diào)用后,再把 reuse的cell從reusableTableCells取出來,放入到visiableCells。

2. reloadRowsAtIndex,刷新指定的IndexPath。如果調(diào)用時(shí)reusableTableCells為空,那么 cellForRowAtIndexPath調(diào)用后,是新創(chuàng)建cell,新的cell加入到visiableCells。老的cell移出 visiableCells,加入到reusableTableCells。于是,之后的刷新就有cell做reuse了。

三十一、遇到tableView卡頓嘛?會(huì)造成卡頓的原因大致有哪些?

1.最常用的就是cell的重用, 注冊(cè)重用標(biāo)識(shí)符

如果不重用cell時(shí),每當(dāng)一個(gè)cell顯示到屏幕上時(shí),就會(huì)重新創(chuàng)建一個(gè)新的cell

如果有很多數(shù)據(jù)的時(shí)候,就會(huì)堆積很多cell。

如果重用cell,為cell創(chuàng)建一個(gè)ID,每當(dāng)需要顯示cell 的時(shí)候,都會(huì)先去緩沖池中尋找可循環(huán)利用的cell,如果沒有再重新創(chuàng)建cell

2.避免cell的重新布局

cell的布局填充等操作 比較耗時(shí),一般創(chuàng)建時(shí)就布局好

如可以將cell單獨(dú)放到一個(gè)自定義類,初始化時(shí)就布局好

3.提前計(jì)算并緩存cell的屬性及內(nèi)容

當(dāng)我們創(chuàng)建cell的數(shù)據(jù)源方法時(shí),編譯器并不是先創(chuàng)建cell 再定cell的高度

而是先根據(jù)內(nèi)容一次確定每一個(gè)cell的高度,高度確定后,再創(chuàng)建要顯示的cell,滾動(dòng)時(shí),每當(dāng)cell進(jìn)入憑虛都會(huì)計(jì)算高度,提前估算高度告訴編譯器,編譯器知道高度后,緊接著就會(huì)創(chuàng)建cell,這時(shí)再調(diào)用高度的具體計(jì)算方法,這樣可以方式浪費(fèi)時(shí)間去計(jì)算顯示以外的cell

4.減少cell中控件的數(shù)量

盡量使cell得布局大致相同,不同風(fēng)格的cell可以使用不用的重用標(biāo)識(shí)符,初始化時(shí)添加控件,

不適用的可以先隱藏

5.不要使用ClearColor,無背景色,透明度也不要設(shè)置為0

渲染耗時(shí)比較長

6.使用局部更新

如果只是更新某組的話,使用reloadSection進(jìn)行局部更

7.加載網(wǎng)絡(luò)數(shù)據(jù),下載圖片,使用異步加載,并緩存

8.少使用addView 給cell動(dòng)態(tài)添加view

9.按需加載cell,cell滾動(dòng)很快時(shí),只加載范圍內(nèi)的cell

10.不要實(shí)現(xiàn)無用的代理方法,tableView只遵守兩個(gè)協(xié)議

11.緩存行高:estimatedHeightForRow不能和HeightForRow里面的layoutIfNeed同時(shí)存在,這兩者同時(shí)存在才會(huì)出現(xiàn)“竄動(dòng)”的bug。所以我的建議是:只要是固定行高就寫預(yù)估行高來減少行高調(diào)用次數(shù)提升性能。如果是動(dòng)態(tài)行高就不要寫預(yù)估方法了,用一個(gè)行高的緩存字典來減少代碼的調(diào)用次數(shù)即可

12.不要做多余的繪制工作。在實(shí)現(xiàn)drawRect:的時(shí)候,它的rect參數(shù)就是需要繪制的區(qū)域,這個(gè)區(qū)域之外的不需要進(jìn)行繪制。例如上例中,就可以用CGRectIntersectsRect、CGRectIntersection或CGRectContainsRect判斷是否需要繪制image和text,然后再調(diào)用繪制方法。

13.預(yù)渲染圖像。當(dāng)新的圖像出現(xiàn)時(shí),仍然會(huì)有短暫的停頓現(xiàn)象。解決的辦法就是在bitmap context里先將其畫一遍,導(dǎo)出成UIImage對(duì)象,然后再繪制到屏幕;

14.使用正確的數(shù)據(jù)結(jié)構(gòu)來存儲(chǔ)數(shù)據(jù)。

三十二、runloop 使用

文章

????????????????????????????????????????????????????????????????????????????????????????????????????????????概念:

運(yùn)行循環(huán),保持程序的運(yùn)行,處理應(yīng)用中的各種事件,有事就做,沒事休息,可以節(jié)省CPU的資源 ,提高程序性能

1、講講 RunLoop,項(xiàng)目中有用到嗎?
2、RunLoop內(nèi)部實(shí)現(xiàn)邏輯?
3、Runloop和線程的關(guān)系?

每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的RunLoop對(duì)象
RunLoop保存在一個(gè)全局的Dictionary里,線程作為key,RunLoop作為value
主線程的RunLoop已經(jīng)自動(dòng)創(chuàng)建好了,子線程的RunLoop需要主動(dòng)創(chuàng)建
RunLoop在第一次獲取時(shí)創(chuàng)建,在線程結(jié)束時(shí)銷毀

4、timer 與 Runloop 的關(guān)系?
5、程序中添加每3秒響應(yīng)一次的NSTimer,當(dāng)拖動(dòng)tableview時(shí)timer可能無法響應(yīng)要怎么解決?
6、Runloop 是怎么響應(yīng)用戶操作的, 具體流程是什么樣的?
7、說說RunLoop的幾種狀態(tài)?
8、Runloop的mode作用是什么?

1、Runloop 的應(yīng)用:
NSTimer 、 imageview 顯示、performselector、常駐線程、自動(dòng)釋放池

2、Runloop 相關(guān)類

//
CFRunLoopRef
// 代表運(yùn)行模式:每次啟動(dòng),只能制定一個(gè)模式,如果需要切換,只能退出當(dāng)前roop,這樣做的目的是為了區(qū)分開不同的 timer/source/observer
CFRunLoopModeRef 
// 事件輸入源  
// 1. Source1 : 基于Port的線程間通信   2. Source0 : 觸摸事件,PerformSelectors
CFRunLoopSourceRef 
// 基于時(shí)間的觸發(fā)器,但是會(huì)受到 mode 的影響,但是GCD定時(shí)器不會(huì)受到影響
CFRunLoopTimerRef 
// 觀察者 監(jiān)聽roop 的狀態(tài)
// 可以監(jiān)聽的時(shí)間點(diǎn):
// 1、即將進(jìn)入kcfRunLoopEntry
// 2、即將處理timer   kcfRunLoopBeforeTimers(????????timer)
// 3、即將處理source  kcfRunLoopBeforeSources(????????source)
// 4、即將進(jìn)入休眠  kcfRunLoopBeforeWaiting(????????????)
// 5、剛從休眠中喚醒 kcfRunLoopAfterWaiting(??????????????)
// 6、退出  kcfRunLoopExit(????????loop) 
CFRunLoopObserverRef

3、Runloop 的實(shí)現(xiàn)機(jī)制 以及在多線程中的使用

實(shí)現(xiàn)機(jī)制:保持程序的運(yùn)行,處理應(yīng)用中的各種事件,有事就做,沒事休息,可以節(jié)省CPU的資源 ,提高程序性能

處理邏輯:
(1)、通知observer ,即將進(jìn)入 runloop
(2)、通知observer ,即將處理 timer
(3)、通知observer ,即將處理 source0
(4)、如果有 source0,處理
(5)、通知observer ,即將休眠
(6)、通知observer ,即將喚醒
(7)、處理未處理的事件
(8)、線程退出

4、autorelease 對(duì)象什么時(shí)候被釋放?
分兩種情況:
1、手動(dòng)干預(yù)釋放:就是制定autoreleasepool ,超出當(dāng)前作用預(yù)就釋放
2、系統(tǒng)自動(dòng)釋放:當(dāng)前runloop退出,就釋放

5、mode 的作用是什么?
主要是用來制定優(yōu)先級(jí)的

6、nstimer 的使用注意事項(xiàng):
(1)、將 nstimer 實(shí)例添加到runloop 的時(shí)候,應(yīng)該注意 類型mode
(2)、不用的時(shí)候 一定要調(diào)用 invalidate 方法 ,不調(diào)用就會(huì)引起內(nèi)存泄漏 而且用 xcode 找不到

7、UITableViewCell 上有一個(gè) UILable ,用于顯示時(shí)間,滑動(dòng)的過程中是否刷新時(shí)間呢?

如果在創(chuàng)建定時(shí)器的過程中使用的是 NSDefaultRunLoopMode 模式,在滑動(dòng)過程中是不會(huì)調(diào)的,因?yàn)?該模式是運(yùn)行在 空閑狀態(tài)下的。默認(rèn)模式的優(yōu)先級(jí)比較低。

8、子線程中performSelector afterDelay

performSelector


今天用幾個(gè)例子來記錄一下performSelector的各種用法和注意事項(xiàng)

performSelector:withObject
此方法同步阻塞當(dāng)前線程 它走完再走后面的方法

performSelectorOnMainThread:withObject:waitUntilDone
此方法可以在主線程或者子線程去調(diào) 但selector方法運(yùn)行在主線程
waitUntilDone:YES 同步阻塞 自己走完再走后面方法
waitUntilDone:NO    異步非阻塞

performSelector:withObject:afterDelay
此方法是異步非阻塞!! 不能在沒有runloop的子線程直接調(diào) 直接調(diào)的話不會(huì)生效
如果想要在子線程中生效可以:

給這個(gè)子線程加runloop
讓這個(gè)方法在一個(gè)你創(chuàng)建的新的帶有runloop的子線程中perform
不用performSelector:withObject:afterDelay改用dispatch_after


    1. afterDelay 方式是使用當(dāng)前線程的定時(shí)器在一定時(shí)間后調(diào)用SEL,NO AfterDelay方式是直接調(diào)用SEL.
    2. 主線程的runloop默認(rèn)開啟,子線程的runloop默認(rèn)不開啟,所以timer在子線程中是不會(huì)執(zhí)行的,需要手動(dòng)開啟runloop。

三十三、weak 與 assign 的區(qū)別

1、區(qū)別

1.修飾變量類型的區(qū)別

weak 只可以修飾對(duì)象。如果修飾基本數(shù)據(jù)類型,編譯器會(huì)報(bào)錯(cuò)-“Property with ‘weak’ attribute must be of object type”。
assign 可修飾對(duì)象,和基本數(shù)據(jù)類型。當(dāng)需要修飾對(duì)象類型時(shí),MRC時(shí)代使用unsafe_unretained。當(dāng)然,unsafe_unretained也可能產(chǎn)生野指針,所以它名字是"unsafe_”。

2.是否產(chǎn)生野指針的區(qū)別

weak 不會(huì)產(chǎn)生野指針問題。因?yàn)閣eak修飾的對(duì)象釋放后(引用計(jì)數(shù)器值為0),指針會(huì)自動(dòng)被置nil,之后再向該對(duì)象發(fā)消息也不會(huì)崩潰。 weak是安全的。
assign 如果修飾對(duì)象,會(huì)產(chǎn)生野指針問題;如果修飾基本數(shù)據(jù)類型則是安全的。修飾的對(duì)象釋放后,指針不會(huì)自動(dòng)被置空,此時(shí)向?qū)ο蟀l(fā)消息會(huì)崩潰。

二、相似

都可以修飾對(duì)象類型,但是assign修飾對(duì)象會(huì)存在問題。

三、總結(jié)

assign 適用于基本數(shù)據(jù)類型如int,float,struct等值類型,不適用于引用類型。因?yàn)橹殿愋蜁?huì)被放入棧中,遵循先進(jìn)后出原則,由系統(tǒng)負(fù)責(zé)管理?xiàng)?nèi)存。而引用類型會(huì)被放入堆中,需要我們自己手動(dòng)管理內(nèi)存或通過ARC管理。
weak 適用于delegate和block等引用類型,不會(huì)導(dǎo)致野指針問題,也不會(huì)循環(huán)引用,非常安全。

三十四、常見的審核 反饋問題有哪些?

文章 http://www.lxweimin.com/p/0de01db729c8

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容