iOS常見面試題,留個印,不定時更新,以作後用...QAQ

 

1.適配問題程序員

雙關問句:你說下關於iOS的適配怎麼處理的?編程

  iOS適配是有兩個的,一是版本適配,即APP要運行在不一樣版本的iOS系統下;其二是屏幕適配,即不一樣的設備上要如何處理保證不一樣大小的屏幕上顯示的正確;windows

版本適配api

  通常作版本是適配是當前最高版本向下兼容兩個版本,若是你是微信這類用戶量巨大的app那麼基本的全部使用版本都要作適配;方法爲base SDK是目前的最高版本,而後development target設置爲想要兼容到的最低版本便可;數組

屏幕適配安全

  屏幕適配經歷過幾個時期服務器

  ①frame適配:須要多套的代碼實現,較爲麻煩;微信

  ②autoResizing適配:只能作父子控件的適配,不可以同級控件作適配;iOS5以前使用;網絡

  ③autoLayout適配:既能夠用來設置父子控件的關係,也能實現同級控件的適配;多線程

    兩個重要的概念:」參照」和」約束」;

    一句經典標準:」全部的約束都是數學的線性關係」;

    在sb中使用autolayout較爲簡單,純代碼方式較爲複雜,爲了解決該問題,第三方」masonry」應運而生;

    autoLayout推出於iOS6,大熱於iOS7,技術的適應期.......

  ④sizeclass,sizeclass是基於autolayout的分屏處理,這點很重要!

 

  注意點:

    autoresizing和autoLayout不可以同時使用;

    不集成第三方使用autoLayout純代碼的方式須要屏蔽掉autoresizing;

 

2.網絡問題

  網絡類的問題相對於其餘有點多元化,即什麼方面都有可能涉及到,好比協議類問題,鏈接類問題等;這裏只作部分說明;

  2.1)協議類問題

    簡單說下你所瞭解的TCP,UDP,HTTP協議.

    凡是涉及協議類的東西,通常和如今流行的直播類相關,如何公司有意朝這個方向或者原本就是這個方面的,這個是必問的題目;

    首先不要侷限於給出的題目,還能夠拓展一下,好比XMPP等這些都會爲你加分;

    TCP:傳輸控制協議;官方介紹Google你懂得;

      通俗的解釋就是:用戶從網絡獲取數據時候須要知足必定的條件,tcp協議就是個條件;

      知足條件能作什麼?若是不知足呢?

      實現TCP協議,既是」三次握手協議」,該條件保證了數據的安全性;

    UDP:用戶數據報協議;

      是一個簡單的數據報的運輸層協議;顧名思義,就是作數據傳遞用的;區別於TCP,他就是不知足那個條件的,即我只要遵循UDP便可,不須要再鏈接前握手確認,由於省了不少步驟,因此速度較快,但沒有回執安全性沒有保障;

    HTTP:超文本傳輸協議;

      該協議是一個」應用層」的協議;

      可能不少人有過這樣的遭遇.....

      遭遇一:http協議和TCP/IP協議有什麼區別?

      遭遇二:http協議和socket有什麼關係?

      遭遇三:tcp/ip和socket有什麼聯繫?

        諸如此類的問題,還能舉出來一堆,並且你都不想面對......究其緣由實際上是對網絡的基本架構不是那麼的清楚,全部咱們從基本的開始提及;

      —->以上網看電影爲例子

      物理層

        該層做用是鏈接兩個或多個計算機,傳遞」0」和」1」的電信號;表明:光纖,同軸電纜;

      數據鏈路層

        處理電信號轉化爲網絡二進制碼再進行傳輸;表明:網橋,交換機,中繼器等;

      網絡層

        尋址,創建鏈接;即給你的電腦與資源電腦創建聯繫關係;(IP->IP),表明:路由器;

      傳輸層

        網絡層接受和發送了信息,但處理不了,不知道傳遞給哪一個應用程序,好比你獲取到了電影,可是不知道該怎麼才能打開,傳輸層經過網卡給應用程序編號,經過傳遞過來信息裏面附帶的編號,把信息給到指定的應用程序;創建了端口(應用程序(電影播放器))與端口的通訊;表明:PC,手機;

        該層協議:

        ->TCP協議:安全鏈接協議/三次握手協議:可以保障信息的安全性。

        ->UDP協議:報文頭協議,不關心是否接受到信息,效率高,但不安全;

      會話層

        創建了一套自動接收和發送信息,自動網絡尋址的機制。

      表示層

        解決不一樣系統之間的語法問題(翻譯官),好比Linux下的QQ和windows下的QQ通訊問題;

      應用層

        規定應用程序的數據傳輸格式。

          http協議:超文本傳輸協議

          file協議:文件傳輸協議

          mail協議:郵件協議

 

       如今上面的問題基本明白的差很少了吧,http協議是一個應用層的協議,主要作的是包裝數據的任務,tcp/ip是傳輸層的協議,主要負責接收和發送數據的任務;socket是對tcp/ip協議的封裝和應用,這個主要是給程序員用的,用來更加容易的處理tcp/ip棧而已;

 

  2.2)多線程問題

    ①概念問題

      說說你對線程和進程的理解?

        進程是程序運行中,是分配和管理資源的基本單位,

        線程能夠看做爲進程中的一部分,能夠理解爲一個輕量級的進程;

          多線程的優缺點(空間和時間的轉換)

           >優勢:

          1)能夠適當的提升程序到執行效率

          2)能夠適當的提升資源到利用率(cpu和內存的利用率)

          3)子線程自動銷燬

           >缺點:

          1)開啓線程會佔用內存空間,若是開啓線程過多會佔用過多的內存,下降程序性能

          2)線程過多,cpu的消耗越大。

          3)線程越多,程序的設計就越複雜,線程之間通訊和資源數據傳遞共享越難。

 

    ②具體操做問題

      你是具體怎麼對線程處理的?

        比較面向對象的處理方法能夠用NSOperation;(是OC基於GCD的封裝);

        效率高一點的可使用GCD; 

          GCD—>

            1>建立隊列

              串行,並行(併發),主隊列,全局

              dispatch_queue_t (隊列類型)

              串並行是creat獲得,主隊列和全局隊列是get獲得

            2>建立任務

              經過block來建立

            3>把任務添加到隊列(指定執行任務函數)

              異步dispatch_async(); 

              同步dispatch_sync();

 

         注意問題:gcd容易涉及到單例,單例的建立分爲好幾種,線程不安全的,線程安全的,須要等待的,一次執行的;通常的建立方式,是」一次執行」的方式;

         方法:static修飾單例對象—>經過dispatch_once_t 判斷;

        NSOperation—>

             a.  NS0peration是一個抽象類(沒有實現方法,用來管理子類)。

             b.  NSOperation的兩個子類:

             >NSInvovcationOperation 

            建立對象,調用star執行操做,star並不會開闢新線程,只有放在NSOperationQueue隊列中,纔會執行異步操做。

            >NSBlockOperation

             建立對象,經過addExecutionBlock添加操做。只要NSBlockOperation封裝操做數 > 1 就會執行異步操做。

         NSOperationQueue->

          >建立對象

          >調用start方法執行操做

           注意:調用start並不會開闢新線程,而是在當前線程下同步執行,只有將NSOperation放到隊列NSOperationQueue中才會執行異步操做。

 

    ③用法問題

      —>什麼地方會使用多線程?

      耗時操做,可使用;但若是多線程使用過多也很差;(詳見時間和空間的解釋);

 

3.第三方問題

  AFN的原理,SDWebImgae的原理,你使用其餘第三方會出現的問題?你是怎麼處理的?本身有沒有寫過一些開源的框架?

   這類第三方問題也是千奇百怪,名氣大的第三方必定要了解,多看下源代碼,對提高頗有用!下面簡單寫個AFN; 

    AFNetworking主要是對NSURLSession和NSURLCollection(iOS9.0廢棄)的封裝,其中主要有如下類:

    AFHTTPRequestOperationManager :內部封裝的是 NSUrlConnection,負責發送網絡請求,使用最多的一個類.(3.0廢棄)

    AFHTTPSessionManager :內部封裝是 NSUrlSession ,負責發送網絡請求,使用最多的一個類.

    AFHTTPRequestOperationManager 和 AFHTTPSessionManager :定義的 API(方法名稱)是如出一轍,沒有任何區別.

    AFNetworkReachabilityManager :實時監測網絡狀態的工具類.當前的網絡環境發生改變以後,這個工具類就能夠檢測到.

    AFSecurityPolicy :網絡安全的工具類, 主要是針對 HTTPS 服務.

    AFURLRequestSerialization :序列化工具類,基類.上傳的數據轉換成JSON格式(AFJSONRequestSerializer).使用很少.

    AFURLResponseSerialization :反序列化工具類;基類.使用比較多:

    AFJSONResponseSerializer; JSON解析器,默認的解析器.

    AFHTTPResponseSerializer; 萬能解析器; JSON和XML以外的數據類型,直接返回二進制數據.對服務器返回的數據不作任何處理.

    AFXMLParserResponseSerializer; XML解析器;

    其它的再也不則過多贅述;

 

4.基礎問題

  基礎問題,看似簡單,其餘裏面有不少的坑,一不當心就會掉進去;

 

  —>你對iOS內存管理怎麼理解的?

    兩個小思考:

      ①過分使用 block 以後,沒法解決循環引用問題。

      ②遇到底層 Core Foundation 對象,須要本身手工管理它們的引用計數時,顯得束手無策

    遠古時代的MRC,到後來2011年WWDC推出的ARC,到2013年蘋果廢除macOS上的垃圾回收,用ARC代替,ARC才真正的崛起;

    一個重要的概念:引用計數;—->一個簡單有效的管理對象的生命週期的方式;

    當咱們建立一個新對象的時候,它的引用計數爲 1,當有一個新的指針指向這個對象時,咱們將其引用計數加 1,當某個指針再也不指向這個對象是,咱們將其引用計數減 1,當對象的引用計數變爲 0 時,說明這個對象再也不被任何指針指向了,這個時候咱們就能夠將對象銷燬,回收內存。因爲引用計數簡單有效,除了 Objective-C 和 Swift 語言外,微軟的 COM(Component Object Model )、C++11(C++11 提供了基於引用計數的智能指針 share_prt)等語言也提供了基於引用計數的內存管理方式。

  —->iOS內存之一:循環引用;

    若是A和B兩個對象互相持有了對方做爲本身的成員變量,只有當本身銷燬的時候,纔會將成員變量的引用計數減一,A依賴於B銷燬,B依賴於A銷燬,就會出現循環引用問題;不止兩對象存在循環引用問題,多個對象依次持有對方,形式一個環狀,也能夠形成循環引用問題,並且在真實編程環境中,環越大就越難被發現。

    解決循環引用問題主要有兩個辦法:

    第一個辦法是我明確知道這裏會存在循環引用,在合理的位置主動斷開環中的一個引用,使得對象得以回收。不過,主動斷開循環引用這種操做依賴於程序員本身手工顯式地控制,至關於回到了之前 「誰申請誰釋放」 的內存管理年代,它依賴於程序員本身有能力發現循環引用而且知道在什麼時機斷開循環引用回收內存(這一般與具體的業務邏輯相關),因此這種解決方法並不經常使用,更常見的辦法是使用弱引用 (weak reference) 的辦法弱引用的實現原理是這樣,系統對於每個有弱引用的對象,都維護一個表來記錄它全部的弱引用的指針地址。當一個對象的引用計數爲 0 時,系統就經過這張表,找到全部的弱引用指針,繼而把它們都置成 nil。

    從這個原理中,咱們能夠看出,弱引用的使用是有額外的開銷的。雖然這個開銷很小,可是若是一個地方咱們確定它不須要弱引用的特性,就不該該盲目使用弱引用。舉個例子,有人喜歡在手寫界面的時候,將全部界面元素都設置成 weak 的,這某種程度上與 Xcode 經過 Storyboard 拖拽生成的新變量是一致的。可是我我的認爲這樣作並不太合適。

    由於咱們在建立這個對象時,須要注意臨時使用一個強引用持有它,不然由於 weak 變量並不持有對象,就會形成一個對象剛被建立就銷燬掉。大部分 ViewController 的視圖對象的生命週期與 ViewController 自己是一致的,沒有必要額外作這個事情。

    早先蘋果這麼設計,是有歷史緣由的。在早年,當時系統收到 Memory Warning 的時候,ViewController 的 View 會被 unLoad 掉。這個時候,使用 weak 的視圖變量是有用的,能夠保持這些內存被回收。可是這個設計已經被廢棄了,替代方案是將相關視圖的 CALayer 對應的 CABackingStore 類型的內存區會被標記成 volatile 類型,通常的內存泄漏問題,能夠經過Xcode自帶的instruments進行檢測;

 

  —->iOS內存之二  Core Foundation 對象的內存管理

   底層的 Core Foundation 對象,在建立時大多以 XxxCreateWithXxx 這樣的方式建立,例如:

    // 建立一個 CFStringRef 對象

    CFStringRef str= CFStringCreateWithCString(kCFAllocatorDefault, 「hello world", kCFStringEncodingUTF8);

      // 建立一個 CTFontRef 對象

    CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT", fontSize, NULL);

   對於這些對象的引用計數的修改,要相應的使用 CFRetain 和 CFRelease 方法。以下所示:

    // 建立一個 CTFontRef 對象

    CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT", fontSize, NULL);

    // 引用計數加 1

    CFRetain(fontRef);

    // 引用計數減 1

    CFRelease(fontRef);

     對於 CFRetain 和 CFRelease 兩個方法,能夠直觀地認爲,這與 Objective-C 對象的 retain 和 release 方法等價。因此對於底層 Core Foundation 對象,咱們只須要延續之前手工管理引用計數的辦法便可。

    除此以外,還有另一個問題須要解決。在 ARC 下,咱們有時須要將一個 Core Foundation 對象轉換成一個 Objective-C 對象,這個時候咱們須要告訴編譯器,轉換過程當中的引用計數須要作如何的調整。這就引入了bridge相關的關鍵字,如下是這些關鍵字的說明:

    __bridge: 只作類型轉換,不修改相關對象的引用計數,原來的 Core Foundation 對象在不用時,須要調用 CFRelease 方法。

    __bridge_retained:類型轉換後,將相關對象的引用計數加 1,原來的 Core Foundation 對象在不用時,須要調用 CFRelease 方法。

    __bridge_transfer:類型轉換後,將該對象的引用計數交給 ARC 管理,Core Foundation 對象在不用時,再也不須要調用 CFRelease 方法。 

    咱們根據具體的業務邏輯,合理使用上面的 3 種轉換關鍵字,就能夠解決 Core Foundation 對象與 Objective-C 對象相對轉換的問題了。

 

    在 ARC 的幫助下,iOS 開發者的內存管理工做已經被大大減輕,可是咱們仍然須要理解引用計數這種內存管理方式的優勢和常見問題,特別要注意解決循環引用問題。對於循環引用問題有兩種主要的解決辦法,一是主動斷開循環引用,二是使用弱引用的方式避免循環引用。對於 Core Foundation 對象,因爲不在 ARC 管理之下,咱們仍然須要延續之前手工管理引用計數的辦法。

    在調試內存問題時,Instruments 工具能夠很好地對咱們進行輔助,善用 Instruments 能夠節省咱們大量的調試時間。

 

—>ARC和MRC怎麼理解的?

    MRC的初衷和實現方法

    任何一個內存對象由系統本身處理釋放的問題,不管建立者也好,持有者也好,不須要去考慮別人是否還在使用同一個內存對象,作好本身該作的就是了,別人的事情別人負責。這個方法是爲了解決C/C++傳統的內存管理方式中內存隨着時間或人員變動形成的臃腫不能處理的問題; 

    理解之一:

      修飾符使用:

      控件使用weak修飾,代理用weak修飾,控件用weak修飾是由於已經有了一個強引用的存在,代理用weak是爲了防止循環引用的存在;

      當修飾可變類型的屬性時,如NSMutableArray、NSMutableDictionary、 NSMutableString,用strong。

      當修飾不可變類型的屬性時,如NSArray、NSDictionary、NSString,用copy。

      由於copy出來的是一個新的,可變的變爲不可變的 ,操做就會crash;(這點很重要~)

     理解之二:

      管理....(我還在總結....)

  

  —>控制器的生命週期是什麼?開發的時候要注意什麼?

      //類的初始化方法

      + (void)initialize;

      //對象初始化方法

      - (instancetype)init;

      //從歸檔初始化

      - (instancetype)initWithCoder:(NSCoder *)coder;

      //加載視圖

      - (void)loadView;

      //將要加載視圖

      - (void)viewDidLoad;

      //將要佈局子視圖

      -(void)viewWillLayoutSubviews;

      //已經佈局子視圖

      -(void)viewDidLayoutSubviews;

      //內存警告

      - (void)didReceiveMemoryWarning;

      //已經展現

      -(void)viewDidAppear:(BOOL)animated;

      //將要展現

      -(void)viewWillAppear:(BOOL)animated;

      //將要消失

      -(void)viewWillDisappear:(BOOL)animated;

      //已經消失

      -(void)viewDidDisappear:(BOOL)animated;

      //被釋放

      -(void)dealloc;

    幾個注意事項:

      ①:initialize函數並不會每次建立對象都調用,只有在這個類第一次建立對象時纔會調用,作一些類的準備工做,再次建立這個類的對象,initalize方法將不會被調用,對於這個類的子類,若是實現了initialize方法,在這個子類第一次建立對象時會調用本身的initalize方法,以後不會調用,若是沒有實現,那麼它的父類將替它再次調用一下本身的initialize方法,之後建立也都不會再調用。所以,若是咱們有一些和這個相關的全局變量,能夠在這裏進行初始化。

    ②:init方法和initCoder方法類似,只是被調用的環境不同,若是用代碼進行初始化,會調用init,從nib文件或者歸檔進行初始化,會調用initCoder。

    ③:loadView方法是開始加載視圖的起始方法,除非手動調用,不然在ViewController的生命週期中沒特殊狀況只會被調用一次。

    ④:viewDidLoad方法是咱們最經常使用的方法的,類中成員對象和變量的初始化咱們都會放在這個方法中,在類建立後,不管視圖的展示或消失,這個方法也是隻會在將要佈局時調用一次。

 

    —>說一下你所瞭解的iOS的SDK.

      這個是個坑,不太瞭解iOS通常都會說錯,一句話歸納:

      Xcode是一個集成開發環境(IDE),它裏面有軟件開發工具(SDK),軟件開發工具(SDK)中包含應用程序編程接口(API)補充一些,Cocoa Touch由蘋果公司提供的軟件開發api,也是蘋果公司針對iPhone應用程序快速開發提供的一個類庫。此庫以一系列框架庫的形式存在,支持開發人員使用用戶界面元素構建圖像化的事件驅動的應用程序。而Cocoa是蘋果公司爲Mac OS X所建立的原生面向對象的API,蘋果的面向對象開發框架,用來生成 Mac OS X 的應用程序。

      其次SDK(Software  Development  Kit)軟件開發工具,Xcode、iPhone模擬器、Interface Builder、Instruments和API集合等一些開發相關的工具等都屬於SDK,iOS SDK最開始是獨立於Xcode發佈的,可是後來和Xcode綁定一塊兒發佈了,即在近期版本的Xcode中已經集成了iOS SDK。

而後IDE(Integrated Development  Environment)被集成好的開發環境,Xcode就是一個iOS的IDE,是一個集成了開發工具(SDK)的IDE。

最後Xcode,也是咱們最爲熟知的,它是運行在操做系統Mac OS X上的IDE,是一個開發環境,開發平臺,是開發OS X APP 和 iOS APP的最快捷的方式。

 

    —>如何自定義control?

 

      純代碼方法:自定義control

        initWithFrame:中添加子控件

         layoutSubviews中設置子控件frame。

        對外設置數據接口,重寫setter方法給子控件設置顯示數據。

        在view controller裏面使用init/initWithFrame:方法建立自定義類,而且給自定義類的frame賦值。

        對自定義類對外暴露的數據接口進行賦值便可。

      xib方法:

         建立xib,在xib中拖入須要添加的控件並設置好尺寸。而且要將這個xib的Class設置爲咱們的自定義類。

         經過IBOutlet的方式,將xib中的控件與自定義類進行關聯。對外設置數據接口,重寫setter方法給子控件設置顯示數據。

         在view controller類裏面加載xib文件就能夠獲得對應的類(這裏不須要再設置自定義類的frame,由於xib已經有了整個view的大小。只須要設置位置。),接着就能夠對類對外的數據接口賦值。

 

  —>開發中strong和weak的使用標準是什麼?弱指針被釋放後變成了什麼?

    詳見上面arc和mrc理解;

  

  —>說一下事件響應者鏈.

    先明確幾個概念

      響應鏈:虛擬的不存的.是由多個響應者構成層次結構;

      響應者:是具備響應和處理事件能力的對象,UIResponder是全部響應者的基類;

      事件: 對於iOS設備用戶來講,觸摸屏幕、晃動設備、經過遙控設施控制設備。

 

        觸屏事件(Touch Event)

        運動事件(Motion Event)

        遠端控制事件(Remote-Control Event

 

      響應者鏈一般是由視圖(UIView)構成的;一個視圖的下一個響應者是它視圖控制器(UIViewController)(若是有的話),而後再轉給它的父視圖(Super View);視圖控制器(若是有的話)的下一個響應者爲其管理的視圖的父視圖;單例的窗口(UIWindow)的內容視圖將指向窗口自己做爲它的下一個響應者,須要指出的是,單例的應用(UIApplication)是一個響應者鏈的終點,它的下一個響應者指向nil,以結束整個循環。

 

      事件分發機制:專業的術語請查閱文檔,我先作簡單的概述.

        ①hit-test view

          當iOS系統檢測到手指觸摸(Touch)操做時會將其打包成一個UIEvent對象,並放入當前活動Application的事件隊列,單例的UIApplication會從事件隊列中取出觸摸事件並傳遞給單例的UIWindow來處理,UIWindow對象首先會使用hitTest:withEvent:方法尋找這次Touch操做初始點所在的視圖(View),即須要將觸摸事件傳遞給其處理的視圖,這個過程稱之爲hit-test view。

        ②hitTest:withEvent

          UIWindow實例對象會首先在它的內容視圖上調用hitTest:withEvent:,此方法會在其視圖層級結構中的每一個視圖上調用pointInside:withEvent:(該方法用來判斷點擊事件發生的位置是否處於當前視圖範圍內,以肯定用戶是否是點擊了當前視圖),若是pointInside:withEvent:返回YES,則繼續逐級調用,直到找到touch操做發生的位置,這個視圖也就是要找的hit-test view。

    hitTest:withEvent:方法的處理流程以下:

      首先調用當前視圖的pointInside:withEvent:方法判斷觸摸點是否在當前視圖內;

      若返回NO,則hitTest:withEvent:返回nil;

      若返回YES,則向當前視圖的全部子視圖(subviews)發送hitTest:withEvent:消息,全部子視圖 的遍歷順序是從最頂層視圖一直到到最底層視圖,即從subviews數組的末尾向前遍歷(採用遞歸方法,從索引值最大的開始),直到有子視圖返回非空對象或者所有子視圖遍歷完畢;

      若第一次有子視圖返回非空對象,則hitTest:withEvent:方法返回此對象,處理結束;

      如全部子視圖都返回非,則hitTest:withEvent:方法返回自身(self)。

 

    注意點:

      1.若是最終hit-test沒有找到第一響應者,或者第一響應者沒有處理該事件,則該事件會沿着響應者鏈向上回溯,若是UIWindow實例和UIApplication實例都不能處理該事件,則該事件會被丟棄;

      2.hitTest:withEvent:方法將會忽略隱藏(hidden=YES)的視圖,禁止用戶操做(userInteractionEnabled=YES)的視圖,以及alpha級別小於0.01(alpha<0.01)的視圖。若是一個子視圖的區域超過父視圖的bound區域(父視圖的clipsToBounds 屬性爲NO,這樣超過父視圖bound區域的子視圖內容也會顯示),那麼正常狀況下對子視圖在父視圖以外區域的觸摸操做不會被識別,由於父視圖的pointInside:withEvent:方法會返回NO,這樣就不會繼續向下遍歷子視圖了。固然,也能夠重寫pointInside:withEvent:方法來處理這種狀況。

      3.咱們能夠重寫hitTest:withEvent:來達到某些特定的目的;

 

   —>通知,代理,block的區別,以及何時使用哪一個?爲何?

      這個問題其實還能夠加上一個KVO.....哈哈;

      代理,特色是一對一的形式,並且邏輯結構很是清晰。實現起來較爲簡單:寫協議 ,設置代理這個屬性,  而後在你想通知代理作事情的方法中調用便可。固然這裏面有一些細節,包括 ①協議定義時,請用關鍵字@required,和@optional來明確代理是否必須實現某些方法 ②代理的類型需用id類型,並寫明要遵照的協議 ③就是在調用代理方法的時候須要判斷代理是否實現該方法。

      通知,通知的優勢很明顯,他是一對多的形式,並且能夠在任意對象之間傳遞,不須要兩者有聯繫,固然他的實現和代理相比較稍微繞一點,註冊,發通知,收通知。這裏面的注意點就是 ①對於系統沒有定義的事件監聽時須要本身發通知,這是你就須要定義一個key,字符串類型,這也是通知的一個弊端,你須要拷貝到收通知的對象,避免寫錯一個字母而沒法收通知的尷尬 ②就是註冊的通知中心須要手動移除,否則除了性能的問題還會有其餘的問題出現,好比說一個控制器消失了以後還有由於某些事件而發出通知,形成不想要的結果。

      block功能比較強大,最大特色就是回調,並且回調時能夠傳入參數,最重要的是,不管在哪調用,block的執行都會回到block建立的地方執行,而非調用的地方。而block自己能夠封裝一段代碼,一段代碼你懂的,不少人在初學時會被搞暈,甚至在block的聲明上就糾結,其實很正常,多用就好。語法的東西 ①聲明分爲3部分 返回值類型 + 變量名 + 參數 好比 成員變量的聲明 void (^myblock)(int a)  

    我的見解:在公司的項目中通常是代理較多的,由於有不少複雜的邏輯;通知比較少用,由於通知太多容易出問題,block通常只是回調使用;

        簡而言之,你用着哪一個爽並且不會出問題,用着就是;

 

  —>說一下消息傳遞機制.

      KVO, delegate,通知,block,target-action 

      看上面....

 

  —>分類和類拓展的區別?

 

    分類可以作到的事情主要是:即便在你不知道一個類的源碼狀況下,向這個類添加擴展的方法。此外,分類可以保證你的實現類和其餘的文件區分開。雖然Category不可以直接(注意:此處是」不可以直接」,也就是能夠經過runtime的方法來給分類添加屬性的!!!)爲類添加新的成員變量,可是Category包含類的全部成員變量,即便是@private的。Category能夠從新定義新方法,也能夠override繼承過來的方法。

類擴展就像匿名(也就是沒有那個括號裏面的名字CustomView)的分類同樣,除了同樣不一樣的是,類擴展聲明必須在@implementation在實現。

    分類和類擴展的類似之處是:均可覺得類添加一個額外的方法;

不一樣之處在於:要添加額外方法,分類必須在第一個@interface中聲明方法,而且在@implementation中提供實現,否則運行時出錯。而類擴展,你添加的方法是一個required API,若是不去實現,編譯器會警告,並且這個方法的聲明能夠不在第一個@interface中去聲明。

 

  —>說一下運行時和運行循環,以及你在項目中是如何用運行時的?

 

    Runloop —運行循環 

    1)用來幹嗎的?

      是一個死循環,保證程序不退出。程序默認一個線程執行一個任務,執行完任務後該線程就over掉了,但主線程不行,主線程一over掉程序就沒有了。主線程沒有事情作的時候會進入休眠狀態等待用戶的交互,用戶只要有了點擊事件,睡眠狀態下的runloop就會被喚醒。查找點擊的位置,由誰來響應點擊事件,把消息發送給對方的對象。

    2) 在程序開發中何時會用到runloop?

      >定時器(NSTimer 和 CADisplayLink)

      >蘋果公開提供的Mode有兩個:KCRunLoopDefaultMode(默認等待用戶交互的) 和 KCTrackingLoopDefaultMode(專門處理滾動視圖的拖動事件)

     目的:保證程序不退出,監聽全部事件!(觸摸/時鐘/網絡)

 

      開發使用:

        >實例化時鐘,添加到運行循環。

        注意:必定要銷燬時鐘,不然會產生循環引用!

 

      >socket 開發,使用runloop 可以監聽網絡端口數據的接收與發送狀況!

          socket 開發,一般用在智能家居開發/遊戲機。

        - 有不少文章介紹 運行循環的實戰, 都會舉例 AFN 2.0的時候 NSURLConnectionURL

        -必需要了解到「自動釋放池」的釋放與建立是與runloop有關的!

 

    RunTime—運行時   「消息機制」

 

    >程序啓動時,首先加載運行時!是OC的底層。

      運行時的應用場景:

      1)關聯對象。仿SDWebImage時,給分類動態添加屬性。作到更好的解耦。簡化使用。

      2)*動態獲取類的屬性。字典轉模型使用!創建NSObject的分類。

        >2.1class_copyPropertyList 獲取類屬性數組

          >遍歷數組

        >2.2property_getName  得到每個屬性的名稱

          >添加到OC的數組

          >free  釋放運行時數組

 

    —>怎麼監聽tableview的移動?

      常見的通常方法是:一般是用KVO或者在scrollViewDidScroll的代理方法中監聽ScrollView/TableView的contentOffset方法來設置導航欄透明度或者是拉伸頂部圖片等操做;

      常見的姿式是在scrollViewDidScroll的代理方法中監聽scrollView.contentOffset.y,會發現有導航欄時scrollView.contentOffset.y初始值可能會等於-64,若是再手動設置tableView.contentInset這個值又會改變,這個時候就須要計算出初始偏移量,而後再算偏移的差值,要是過幾天再改下需求......從新計算 

 

 

5.項目經驗問題

    —>app上架後,出現閃退bug如何處理?

 

    使用第三方的工具(好比騰訊的bugly),採用hotfix—jspatch解決,閃退的緣由有好多,

      1)內存問題—>能夠經過Instruments工具中的Allocations 和 Leaks模塊庫來發現內存分配問題和內存泄漏問題。

      2)響應超時,能夠看下crash日誌

      3)應用邏輯的bug,這類bug是閃退的主要緣由,能夠分析下崩潰日誌來查找;

 

    —>你所維護的app的崩潰率是多少?怎麼統計的?

        和上個問題基本差很少

 

    —>開發過程當中遇到的比較難處的bug是什麼?

      本身的bug本身最清楚......

      像什麼新老版本之中有些技術已通過時了,卻在老項目中還繼續存在,固然會有問題....

  

    —>你是怎麼作的支付?

        支付類,一句話」好好看,要聽話」;

        集成支付的東西,首要看」業內大哥」(支付寶,微信,銀聯…)的官方文檔,讓怎麼作就怎麼作!!!

 

    —>怎麼處理token值過時?

        簡單來講,token值是用來標識用戶的一個值;即讓服務器知道」你是誰?」

        若是 app 是新聞類/遊戲類/聊天類等須要長時間用戶粘性的. 通常能夠設置1年的有效時間!若是 app 是 支付類/銀行類的. 通常token只得有效時間比較短: 15分鐘左右!

       token值 失效後 會從新進行登陸;用戶體檢很差,能夠增長一個時間字段記錄token值將要過時時間,而後在快要過期間裏用戶打開app的時候,設定從新登陸;

 

     最後,↖(^ω^)↗,加油吧 少年!

相關文章
相關標籤/搜索