日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS 开发者 2019 面试总结

發(fā)布時間:2023/12/18 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS 开发者 2019 面试总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言:致一個開發(fā)者,有一個學(xué)習(xí)的氛圍跟一個交流圈子特別重要這是一個我的iOS交流群:869685378,不管你是小白還是大牛歡迎入駐 ,分享BAT,阿里面試題、面試經(jīng)驗,討論技術(shù), 大家一起交流學(xué)習(xí)成長!

?

在投遞簡歷之前,就是所謂的寒冬將至,開個年會都是守望寒冬,然后我身邊的準(zhǔn)備跳槽的大佬們,都是有幾分涼意,不過我還好,總感覺一個人吃飽,全家不餓,O(∩_∩)O哈!沒想那么多,直接就全身投入,找工作。現(xiàn)在做個回顧吧,為自己,也為路過的各位大俠。


先說一個問題,是寒冬嗎?我真沒覺得,說自己的一個親身體會,不夸張的說,基本上是每天2家,且持續(xù)一個月,當(dāng)然是距離可以接受,公司小中大都有的,我感覺不是互聯(lián)網(wǎng)的寒冬,是自己的寒冬,有一句說的很好,人生就兩季,努力是旺季,不努力是淡季!我感覺很有道理~~~~


現(xiàn)在面試要求高在要會各種語言,另外要很深入,要夠底層,要懂?dāng)?shù)據(jù)結(jié)構(gòu)與算法之美(面試過的都會體會什么是真是一言難盡吧),看一些大佬,進(jìn)入一個大廠,也寫了自己的準(zhǔn)備,我感覺真是有付出有回報的,也看出自己的一些不足吧!so,革命尚未成功,同志們?nèi)孕枧Ψ?#xff01;!

?

知識點總結(jié)

?

因為自己水平有限,可能有些路過的大佬感覺比較簡單,我也總結(jié)了下,請飄過~~還有一些答案僅供參考,如有錯誤,請不吝賜教,在此謝過—->

?

+(void)initinstance 與 +(void)load兩個方法的區(qū)別于比較//小紅書面試問題\

?

先看下面表格兩者的區(qū)別,后續(xù)會繼續(xù)介紹

?

?+load+initialize
調(diào)用時機被添加runtime時收到第一條消息時,可能永遠(yuǎn)不調(diào)用
調(diào)用順序父類->子類->分類父類->子類
調(diào)用次數(shù)1次多次
是否需要顯示調(diào)用父類實現(xiàn)
是否沿用父類的實現(xiàn)
分類中的實現(xiàn)類和分類都執(zhí)行?

?

相同點:

?

  • 系統(tǒng)都執(zhí)行一次。

  • 假如父類和子類都被調(diào)用,父類在子類之前被調(diào)用

  • ?

    不同點:

    ?

    ?

  • load 方法會在加載類的時候就被調(diào)用,也就是 ios 應(yīng)用啟動的時候,就會加載所有的類,就會調(diào)用每個類的 + load 方法。

  • +initialize 這個方法會在 第一次初始化這個類之前 被調(diào)用,我們用它來初始化靜態(tài)變量

  • load 會在main()函數(shù)之前調(diào)用。initialize 則在類實例化 或 類方法被調(diào)用時調(diào)用;

  • 如果子類中沒有initialize方法,則會再次調(diào)用父類的initialize方法,類別會覆蓋主類的initialize,load則不會被覆蓋

  • load順序在 initialize之前;

  • ????initialize 方法的調(diào)用看起來會更合理,通常在它里面寫代碼比在 + load 里寫更好,因為它是懶調(diào)用的,也有可能完全不被調(diào)用。類第一次被加載時,

  • 類接收消息時,運行時會先檢查 + initialize 有沒有被調(diào)用過。如果沒有,會在消息被處理前調(diào)用

  • ?

    —>>>>
    initialize 最終是通過 objc_msgSend 來執(zhí)行的,objc_msgSend 會執(zhí)行一系列方法查找,并且 Category 的方法會覆蓋類中的方法
    load 是在被添加到 runtime 時開始執(zhí)行,父類最先執(zhí)行,然后是子類,最后是 Category。又因為是直接獲取函數(shù)指針來執(zhí)行,不會像 objc_msgSend 一樣會有方法查找的過程。

    ?

    —->>>>

    ?

    怎么實現(xiàn)單例, 2種方法實現(xiàn)//喜馬拉雅面試問題\

    ?

    ?

    ?

    //第一種方式:線程安全的單例2(不推薦 效率低) +?(instancetype)shareSingleton2?{@synchronized(self)?{if?(!singleton)?{singleton?=?[[self?alloc]init];}}return?singleton; }//第二種方式?線程安全的單例 +?(instancetype)shareSingleton?{static?dispatch_once_t?onceToken;dispatch_once(&onceToken,?^{singleton?=?[[self?alloc]init];});return?singleton; }

    ?

    ?

    然而僅僅知道這些是不夠的,說了上面的,面試官會繼續(xù)問單例,怎么實現(xiàn)的,加鎖了嗎?單例什么時候釋放?然后你就會一臉懵~有同感的舉個手

    ?

    • 單例,怎么實現(xiàn)的,加鎖了嗎?單例什么時候釋放
      其實在上面的兩個單例的創(chuàng)建中,@synchronized是一個鎖,后面會講到,就是說第一種是通過加鎖的方式來實現(xiàn),而第二種解析如下:
      GCD創(chuàng)建:dispatch_once中dispatch_once_t類型為typedef long
      ? ? onceToken= 0,線程執(zhí)行dispatch_once的block中代碼
      ? ? onceToken= -1,線程跳過dispatch_once的block中代碼不執(zhí)行
      ? ? onceToken= 其他值,線程被線程被阻塞,等待onceToken值改變
      用途:限制創(chuàng)建,提供全局調(diào)用,節(jié)約資源和提高性能。參考
      常見的應(yīng)用場景:
      ? ? UIApplication
      ? ? NSNotificationCenter
      ? ? NSFileManager
      ? ? NSUserDefaults
      ? ? NSURLCache
      ? ? NSHTTPCookieStorage

    ?


    ?

    那么單例是怎么銷毀的呢?如下:

    ?

    ?

    ?

    ?

    方法一: +(void)attemptDealloc{[_instance?release];?//mrc?需要釋放,當(dāng)然你就不能重寫release的方法了._instance?=?nil; }方法二: 1.?必須把static?dispatch_once_t?onceToken;?這個拿到函數(shù)體外,成為全局的. 2. +(void)attempDealloc{onceToken?=?0;?//?只有置成0,GCD才會認(rèn)為它從未執(zhí)行過.它默認(rèn)為0.這樣才能保證下次再次調(diào)用shareInstance的時候,再次創(chuàng)建對象.[_instance?release];_instance?=?nil;}

    ?

    ?

    數(shù)據(jù)持久化

    ?

    ?

    下面說下數(shù)據(jù)持久化吧?如果是在2年前,你說了數(shù)據(jù)持久化有NSUserDefaults,plist,歸檔,CoreData巴拉巴拉,感覺這位童靴還闊以,但是現(xiàn)在就有點low了,你懂得~
    面試大佬會問有幾種?然后每種有什么不同?什么能存儲什么不能存儲?每個在具體使用應(yīng)該注意什么?等等,問到你懷疑人生

    ?

    • 屬性列表(plist存儲)通常叫做plist文件,用于存儲在程序中不經(jīng)常修改、數(shù)據(jù)量小的數(shù)據(jù),不支持自定義對象存儲,支持?jǐn)?shù)據(jù)存儲的類型為:Array,Dictionary,String,Number,Data,Date,Boolean,通常用來存放接口名、城市名、銀行名稱、表情名等極少修改的數(shù)據(jù)
      plist文件是將某些特定的類,通過xml的方式保存在目錄中。

    ?

    ?

    • 偏好設(shè)置(NSUserDefaults)
      用于存儲用戶的偏好設(shè)置,同樣適合于存儲輕量級的用戶數(shù)據(jù),數(shù)據(jù)會自動保存在沙盒的Libarary/Preferences目錄下,本質(zhì)上就是一個plist文件,所以同樣的不支持自定義對象存儲,支持?jǐn)?shù)據(jù)存儲的類型為:Array,Dictionary,String,Number,Data,Date,Boolean,可以用做檢查版本是否更新、是否啟動引導(dǎo)頁、自動登錄、版本號等等,需要注意的是NSUserDefaults是定時的將緩存中的數(shù)據(jù)寫入磁盤,并不是即時寫入,為了防止在寫完NSUserDefaults后,程序退出導(dǎo)致數(shù)據(jù)的丟失,可以在寫入數(shù)據(jù)后使用synchronize強制立即將數(shù)據(jù)寫入磁盤
      如果這里你沒有調(diào)用synchronize方法的話,系統(tǒng)會根據(jù)I/O情況不定時刻地保存到文件中。所以如果需要立即寫入文件的就必須調(diào)用synchronize方法。

    ?

    ?


    ?

    PS: 在這里說了小問題,就是有面試官會問,你在開發(fā)中用NSUserDefaults有沒有什么坑?你可以這樣答:比如你存儲一個值時,沒有進(jìn)行及時的調(diào)用synchronize方法,然后此時程序就crash了或者強制殺死,那么你再下次去取值的時候,就會取不到你之前存儲的值,路過的大佬可以試下~~

    ?

    • 歸檔序列化存儲
      歸檔可以直接將對象存儲為文件,也可將文件直接解歸檔為對象,相對于plist文件與偏好設(shè)置數(shù)據(jù)的存儲更加多樣,支持自定義的對象存儲,歸檔后的文件是加密的,也更加的安全,文件存儲的位置可以自定義。
      遵守NSCoding或者NSSecureCoding協(xié)議

    ?

    ?

    ?

    • 沙盒存儲
      可以提高程序的體驗度,為用戶節(jié)約數(shù)據(jù)流量,主要在用戶閱讀書籍、聽音樂、看視頻等,在沙盒中做數(shù)據(jù)的存儲,主要包含文件夾:Documents: 最常用的目錄,存放重要的數(shù)據(jù),iTunes同步時會備份該目錄Library/Caches: 一般存放體積大,不重要的數(shù)據(jù),iTunes同步時不會備份該目錄Library/Preferences: 存放用戶的偏好設(shè)置,iTunes同步時會備份該目錄tmp: 用于存放臨時文件,在程序未運行時可能會刪除該文件夾中的數(shù)據(jù),iTunes同步時不會備份該目錄

    ?

    ?

    • Core Data
      Core Data是框架,并不是數(shù)據(jù)庫,該框架提供了對象關(guān)系的映射功能,使得能夠?qū)C對象轉(zhuǎn)換成數(shù)據(jù),將數(shù)據(jù)庫中的數(shù)據(jù)還原成OC對象,在轉(zhuǎn)換的過程中不需要編寫任何的SQL語句,在Core Data中有三個重要的概念:
      NSPersistentStoreCoordinator:持久化存儲協(xié)調(diào)器,在NSPersistentStoreCoordinator中包含了持久化存儲區(qū),在持久化存儲區(qū)中包含了數(shù)據(jù)表中的很多數(shù)據(jù),持久化存儲區(qū)的設(shè)置通常選擇NSSQLiteStoreType,也就是選擇SQLite數(shù)據(jù)庫
      NSManagedObjectModel:托管對象模型,用于描述數(shù)據(jù)結(jié)構(gòu)的模型

    ?

    ?

    • SQLite3
      SQLite是輕量級的數(shù)據(jù)庫,占用資源很少,最初是用于嵌入式的系統(tǒng),在iOS中使用SQLite,需要加入”libsqlite3.tbd”依賴庫并導(dǎo)入頭文件。不應(yīng)該頻繁的打開關(guān)閉數(shù)據(jù)庫,有可能會影響性能, 應(yīng)在啟動程序時打開數(shù)據(jù)庫,在退出程序是關(guān)閉數(shù)據(jù)庫

      ?

    ?

    ?

    • FMDB
      FMDB以O(shè)C的方式封裝了SQLite的C語言API,減去了冗余的C語言代碼,使得API更具有OC的風(fēng)格,更加的面向?qū)ο?#xff0c;相對于Core Data框架更加的輕量級,FMDB還提供了多線程安全的數(shù)據(jù)庫操作方法,在FMDB中有三個重要的概念:
      FMDatabase:一個FMDatabase就代表一個SQLite數(shù)據(jù)庫,執(zhí)行sql語句
      FMResultSet:執(zhí)行查詢后的結(jié)果集
      FMDatabaseQueue:用于在多線程中執(zhí)行多個查詢或更新,安全的

    ?

    ===
    緊接著說下CoreData吧?它總是比你知道的還要多?
    CoreData中的多線程問題

    ?

    主要推薦的實施方案,也是最優(yōu)方案,如下:
    1.使用一個NSPersistentStoreCoordinator,以及兩個獨立的Contexts,一個context負(fù)責(zé)主線程與UI協(xié)作,一個context在后臺負(fù)責(zé)耗時的處理,用Notifications的方式通知主線程的NSManagedObjectContext進(jìn)行mergeChangesFromContextDidSaveNotification操作

    ?

    2.后臺線程做讀寫更新,而主線程只讀

    ?

    3.CoreData中的NSManagedObjectContext在多線程中不安全,如果想要多線程訪問CoreData的話,最好的方法是一個線程一個NSManagedObjectContext,每個NSManagedObjectContext對象實例都可以使用同一個NSPersistentStoreCoordinator實例,這個實例可以很安全的順序訪_問永久存儲,這是因為NSManagedObjectContext會在便用NSPersistentStoreCoordinator前上鎖。ios5.0為NSManagedObjectContext提供了initWithConcurrentcyType方法,其中的一個NSPrivateQueueConcurrencyType,會自動的創(chuàng)建一個新線程來存放NSManagedObjectContext而且它還會自動創(chuàng)建NSPersistentStoreCoordinator,

    ?


    ?

    CoreData里面還帶有一個通知NSManagedObjectContextDidSaveNotification,主要監(jiān)聽NSManagedObjectContext的數(shù)據(jù)是否改變,并合并數(shù)據(jù)改變到相應(yīng)context。

    ?

    面試官問的Context是那兩種?這個面試官問的應(yīng)該是用到的那兩個Type?
    答:NSConfinementConcurrencyType ? NSMainQueueConcurrencyType

    ?

    ?

    ?

    //創(chuàng)建并行的NSManagedObjectContext對象 [[NSManagedObjectContext?alloc]?initWithConcurrencyType:NSPrivateQueueConcurrencyType];ps:NSConfinementConcurrencyType?(或者不加參數(shù),默認(rèn)就是這個)NSMainQueueConcurrencyType?(表示只會在主線程中執(zhí)行)

    ?

    ?

    接著談?wù)剶?shù)據(jù)庫的優(yōu)化問題,可以通過以下幾點進(jìn)行優(yōu)化

    ?

    • FMDB事務(wù)批量更新數(shù)據(jù)庫速度問題。(親測可以呀—740條數(shù)據(jù)用和不用事務(wù)效率差別20倍+)

    • 寫同步(synchronous)
      在SQLite中,數(shù)據(jù)庫配置的參數(shù)都由編譯指示(pragma)來實現(xiàn)的,而其中synchronous選項有三種可選狀態(tài),分別是full、normal、off
      設(shè)置為synchronous OFF (0)時,SQLite在傳遞數(shù)據(jù)給系統(tǒng)以后直接繼續(xù)而不暫停

    • 一條SQL語句插入多條數(shù)據(jù)

    • 在事務(wù)中進(jìn)行插入處理。

    • 數(shù)據(jù)有序插入。

    ?

    ?

    ?

    ?

    ?


    ?

    再說下什么是事務(wù)?\英語流利說總監(jiān)面試問題//


    事務(wù):

    ?

    • 作為單個邏輯工作單元執(zhí)行的一系列操作,而這些邏輯工作單元需要具有原子性,一致性,隔離性和持久性

    • 是并發(fā)控制的基本單元。所謂的事務(wù),它是一個操作序列,這些操作要么都執(zhí)行,要么都不執(zhí)行,它是一個不可分割的工作單元。例如,銀行轉(zhuǎn)賬工作:從一個賬號扣款并使另一個賬號增款,這兩個操作要么都執(zhí)行,要么都不執(zhí)行。所以,應(yīng)該把它們看成一個事務(wù)。

    • 事務(wù)是一種機制,用于維護(hù)數(shù)據(jù)庫的完整性

    ?

    ?

    ?


    ?

    事務(wù)基本特征:

    ?

    • 原子性(Atomicity):事務(wù)的個元素是不可分的,事務(wù)是一個完整的操作,一個操作序列,要么都執(zhí)行,要么都不執(zhí)行

    • 一致性(Consistemcy):事務(wù)完成時,數(shù)據(jù)必須是一致的,保證數(shù)據(jù)的無損

    • 隔離性(Isolation):多個事務(wù)彼此隔離,事務(wù)必須是獨立的,任何事務(wù)都不應(yīng)該受影響

    • 持久性(Durability):事務(wù)完成之后,它對于系統(tǒng)的影響是永久的,該修改即使出現(xiàn)系統(tǒng)故障也將一直保留,真實的修改了數(shù)據(jù)庫

    ?

    五種 Mach-O 類型的淺要分析

    ?

    這個面試題針對我自己的簡歷,可略過~

    ?

    在制作Framework時,可以設(shè)置framework中的Mach-O Type,不手動修改的默認(rèn)配置即為 Dynamic Library,在SDK中默認(rèn)使用的是 Relocatable Object File

    ?

    ?

    Executable: 可執(zhí)行二進(jìn)制文件

    dynamic Library 動態(tài)庫
    Bundle :非獨立二進(jìn)制文件,顯示加載
    static Library 靜態(tài)庫
    Relocatable Object File: 可重定位的目標(biāo)文件,中間結(jié)果

    ?


    ?

    Relocatable Object File 是組裝靜態(tài)庫和動態(tài)庫的零件,而靜態(tài)庫和動態(tài)庫就是可執(zhí)行二進(jìn)制文件的組件。這里用了零件和組件的概念,零件是不可缺少的,組件則是可選的

    ?

    Dynamic Library 更靈活;復(fù)用性更強;且就安全來說,統(tǒng)一放置在 Payload/Framework 目錄下的自建的動態(tài)庫,不參與應(yīng)用的加殼操作,安全性稍遜一籌
    Relocatable Object File 以及 Static Library 都是在編譯后直接合并到最后的可執(zhí)行文件中的,缺點相對不夠靈活,但安全性稍強。

    ?

    如果要偏向靜態(tài)的方案,應(yīng)該選擇 Relocatable Object File 還是 Static Library?
    使用 Relocatable Object File 可以減少二進(jìn)制文件的大小

    ?

    動態(tài)庫和靜態(tài)庫的區(qū)別:
    如果使用動態(tài)庫,需要考慮的是:

    ?

  • 對于啟動速度的影響。

  • 對于保密要求高的線下渠道 SDK,可能會被從 .app/ 中單獨拿出來,反編譯研究具體實現(xiàn)。靜態(tài)庫則比較安全一點。

  • ?

    內(nèi)存管理

    ?

    Objective-C的內(nèi)存管理主要有三種方式ARC(自動內(nèi)存計數(shù))、手動內(nèi)存計數(shù)、內(nèi)存池。

    ?

    1). 自動內(nèi)存計數(shù)ARC:由Xcode自動在App編譯階段,在代碼中添加內(nèi)存管理代碼。
    2). 手動內(nèi)存計數(shù)MRC:遵循內(nèi)存誰申請、誰釋放;誰添加,誰釋放的原則。
    3). 內(nèi)存釋放池Release Pool:把需要釋放的內(nèi)存統(tǒng)一放在一個池子中,當(dāng)池子被抽干后(drain),池子中所有的內(nèi)存空間也被自動釋放掉。內(nèi)存池的釋放操作分為自動和手動。自動釋放受runloop機制影響。

    ?

    有一個很經(jīng)典的面試題,考察自動釋放池的如下:

    ?

    ?

    ?

    ?for?(int?i?=?0;?i?<?MAXFLOAT;?i++)?{NSString?*string?=?@"stdy";string?=?[string?lowercaseString];string?=?[string?stringByAppendingString:@"123"];NSLog(@"--%@",?string);}

    ?

    上述的這種寫法,會使內(nèi)存慢慢增加,如何解決呢,面試官想要的答案就是用自動釋放池,你也可以改成其他的,但不是面試官要的,你懂的,修改如下:

    ?

    ?

    ?

    for?(int?i?=?0;?i?<?MAXFLOAT;?i++)?{@autoreleasepool?{NSString?*string?=?@"stdy";string?=?[string?lowercaseString];string?=?[string?stringByAppendingString:@"123"];NSLog(@"--%@",?string);}}

    ?

    • 什么時間會創(chuàng)建自動釋放池?*
      從程序啟動到加載完成是一個完整的運行循環(huán),然后會停下來,等待用戶交互,用戶的每一次交互都會啟動一次運行循環(huán),來處理用戶所有的點擊事件、觸摸事件,運行循環(huán)檢測到事件并啟動后,就會創(chuàng)建自動釋放池。
      子線程的 runloop 默認(rèn)是不工作,無法主動創(chuàng)建,必須手動創(chuàng)建。
      自定義的 NSOperation 和 NSThread 需要手動創(chuàng)建自動釋放池。比如:自定義的 NSOperation 類中的 main 方法里就必須添加自動釋放池。否則出了作用域后,自動釋放對象會因為沒有自動釋放池去處理它,而造成內(nèi)存泄露。

    ?

    但對于 blockOperation 和 invocationOperation 這種默認(rèn)的Operation ,系統(tǒng)已經(jīng)幫我們封裝好了,不需要手動創(chuàng)建自動釋放池。
    @autoreleasepool 當(dāng)自動釋放池被銷毀或者耗盡時,會向自動釋放池中的所有對象發(fā)送 release 消息,釋放自動釋放池中的所有對象。
    如果在一個vc的viewDidLoad中創(chuàng)建一個 Autorelease對象,那么該對象會在 viewDidAppear 方法執(zhí)行前就被銷毀了。

    ?

    什么會造成離屏渲染

    ?

    GPU屏幕渲染有兩種方式:
    (1)On-Screen Rendering (當(dāng)前屏幕渲染)
    指的是GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)進(jìn)行。
    (2)Off-Screen Rendering (離屏渲染)
    指的是在GPU在當(dāng)前屏幕緩沖區(qū)以外開辟一個緩沖區(qū)進(jìn)行渲染操作。

    ?

    下面的情況或操作會引發(fā)離屏渲染:

    ?

    • 為圖層設(shè)置遮罩(layer.mask)

    • 將圖層的layer.masksToBounds / view.clipsToBounds屬性設(shè)置為true

    • 將圖層layer.allowsGroupOpacity屬性設(shè)置為YES和layer.opacity小于1.0

    • 為圖層設(shè)置陰影(layer.shadow *)。

    • 為圖層設(shè)置layer.shouldRasterize=true

    • 具有l(wèi)ayer.cornerRadius,layer.edgeAntialiasingMask,layer.allowsEdgeAntialiasing的圖層

    • 文本(任何種類,包括UILabel,CATextLayer,Core Text等)。

    • 使用CGContext在drawRect :方法中繪制大部分情況下會導(dǎo)致離屏渲染,甚至僅僅是一個空的實現(xiàn)。

    ?

    ?


    ?

    優(yōu)化:

    ?

    1、圓角優(yōu)化
    方案1 :使用貝塞爾曲線UIBezierPath和Core Graphics框架畫出一個圓角

    方案2 :使用CAShapeLayer和UIBezierPath設(shè)置圓角

    ?

    2、shadow優(yōu)化
    對于shadow,如果圖層是個簡單的幾何圖形或者圓角圖形,我們可以通過設(shè)置shadowPath來優(yōu)化性能,能大幅提高性能

    ?

    其他優(yōu)化:

    ?

    當(dāng)我們需要圓角效果時,可以使用一張中間透明圖片蒙上去使用ShadowPath指定layer陰影效果路徑
    使用異步進(jìn)行l(wèi)ayer渲染(Facebook開源的異步繪制框架AsyncDisplayKit)
    設(shè)置layer的opaque值為YES,
    減少復(fù)雜圖層合成盡量使用不包含透明(alpha)通道的圖片資源
    盡量設(shè)置layer的大小值為整形值
    直接讓美工把圖片切成圓角進(jìn)行顯示,這是效率最高的一種方案很多情況下用戶上傳圖片進(jìn)行顯示,
    可以讓服務(wù)端處理圓角使用代碼手動生成圓角Image設(shè)置到要顯示的View上,
    利用UIBezierPath(CoreGraphics框架)畫出來圓角圖片

    ?

    網(wǎng)絡(luò)通信

    ?

    ? ? 1、應(yīng)用層 協(xié)議有:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP
    ? ? 2、表示層 數(shù)據(jù)的表示、安全、壓縮,格式有:JPEG、ASCll、DECOIC、加密格式等(數(shù)據(jù)格式化,代碼轉(zhuǎn)換,數(shù)據(jù)加密),沒有協(xié)議
    ? ? 3、會話層 建立、管理、終止會話,沒有協(xié)議
    ? ? 4、傳輸層 定義傳輸數(shù)據(jù)的協(xié)議端口號,以及流控和差錯校驗。協(xié)議有:TCP UDP,數(shù)據(jù)包一旦離開網(wǎng)卡即進(jìn)入網(wǎng)絡(luò)傳輸層
    ? ? 5、網(wǎng)絡(luò)層 進(jìn)行邏輯地址尋址,實現(xiàn)不同網(wǎng)絡(luò)之間的路徑選擇。協(xié)議有:ICMP IGMP IP(IPV4 IPV6) ARP RARP
    ? ? 6、數(shù)據(jù)鏈路層 建立邏輯連接、進(jìn)行硬件地址尋址、差錯校驗 等功能。(由底層網(wǎng)絡(luò)定義協(xié)議)將比特組合成字節(jié)進(jìn)而組合成幀,用MAC地址訪問介質(zhì),錯誤發(fā)現(xiàn)但不能糾正。協(xié)議有:SLIP CSLIP PPP MTU ARP[鏈接:https://baike.baidu.com/item/A?… addin]RARP
    ? ? 7、物理層 建立、維護(hù)、斷開物理連接。以二進(jìn)制數(shù)據(jù)形式在物理媒體上傳輸數(shù)據(jù)(由底層網(wǎng)絡(luò)定義協(xié)議)協(xié)議有:ISO2110 IEEE802 IEEE802.2

    ?

    ===

    ?

    TPC/IP協(xié)議是傳輸層協(xié)議,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸

    ?

    HTTP是應(yīng)用層協(xié)議,主要解決如何包裝數(shù)據(jù)

    ?

    我們在傳輸數(shù)據(jù)時,可以只使用(傳輸層)TCP/IP協(xié)議,但是那樣的話,如果沒有應(yīng)用層,便無法識別數(shù)據(jù)內(nèi)容,如果想要使傳輸?shù)臄?shù)據(jù)有意義,則必須使用到應(yīng)用層協(xié)議,應(yīng)用層協(xié)議有很多,比如HTTP、FTP、TELNET等,也可以自己定義應(yīng)用層協(xié)議

    ?

    TCP和UDP使用該協(xié)議從一個網(wǎng)絡(luò)傳送數(shù)據(jù)包到另一個網(wǎng)絡(luò)。把IP想像成一種高速公路,它允許其它協(xié)議在上面行駛并找到到其它電腦的出口。TCP和UDP是高速公路上的“卡車”,它們攜帶的貨物就是像HTTP,文件傳輸協(xié)議FTP這樣的協(xié)議等。

    ?

    ===========

    ?

    什么是Socket?

    ?

  • Socket其實并不是一個協(xié)議 而是一個通信模型。它是為了方便大家直接使用更底層協(xié)議(TCP | UDP)而存在的抽象層

  • Socket是對 TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個調(diào)用的接口(API),主要用來一臺電腦的兩個進(jìn)程通信,

  • Socket在網(wǎng)絡(luò)通信中,它涵蓋了網(wǎng)絡(luò)層、傳輸層、會話層、表示層、應(yīng)用層,因為其信時候用到了IP和端口,僅這兩個就表明了它用到了網(wǎng)絡(luò)層和傳輸層,而且它無視多臺電腦通信的系統(tǒng)差別,所以它涉及了表示層,一般Socket都是基于一個應(yīng)用程序的,所以會涉及到會話層和應(yīng)用層

  • ?

    什么是WebSocket,解決了什么問題?//英語流利說面\

    ?

  • WebSocket是應(yīng)用層第七層上的一個應(yīng)用層協(xié)議,它必須依賴 HTTP 協(xié)議進(jìn)行一次握手 ,握手成功后,數(shù)據(jù)就直接從 TCP 通道傳輸,與 HTTP 無關(guān)了

  • Websocket的數(shù)據(jù)傳輸是frame形式傳輸?shù)?#xff0c;比如會將一條消息分為幾個frame,按照先后順序傳輸出去。這樣做會有幾個好處:
    ? ? 1) 大數(shù)據(jù)的傳輸可以分片傳輸,不用考慮到數(shù)據(jù)大小導(dǎo)致的長度標(biāo)志位不足夠的情況。
    ? ? 2 )和http的chunk一樣,可以邊生成數(shù)據(jù)邊傳遞消息,即提高傳輸效率。

  • 總之:WebSocket 的實現(xiàn)分為握手,數(shù)據(jù)發(fā)送/讀取,關(guān)閉連接。

  • ?

    什么是心跳?

  • 心跳就是用來檢測TCP連接的雙方是否可用

  • 客戶端發(fā)起心跳Ping(一般都是客戶端),假如設(shè)置在10秒后如果沒有收到回調(diào),那么說明服務(wù)器或者客戶端某一方出現(xiàn)問題,這時候我們需要主動斷開連接。

  • ?

    HTTP 的幾種請求方式?以及區(qū)別 \英語流利說//

    ?

    英語流利說總監(jiān)問了一個HTTP的PUT請求,下面看下各個請求的不同之處吧
    HTTP1.0定義了三種請求方法:GET, POST 和 HEAD方法。
    HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
    HTTP協(xié)議使用的是URI,是一種表示資源標(biāo)志,那么對應(yīng)的HTTP Verb就是各種對資源的操作,GET,PUT,DELETE等,明確這些,再往下看。可參考
    HTTP: Hyper Text Transfer Protocol,超文本傳輸協(xié)議URI: Universal Resource Identifier,統(tǒng)一資源標(biāo)識符URL: Universal Reversource Locator,統(tǒng)一資源定位符
    簡單地說,URI是在某一規(guī)則下能把資源獨一無二地標(biāo)識出來,URL是特殊的URI,即用定位的方式實現(xiàn)URI

    ?

    GET 請求指定的頁面信息,并返回實體主體。
    HEAD 類似于get請求,只不過返回的響應(yīng)中沒有具體的內(nèi)容,用于獲取報頭。
    PUT:從客戶端向服務(wù)器傳送的數(shù)據(jù)取代指定的文檔的內(nèi)容, 用PUT來達(dá)到更改資源,需要client提交資源全部信息,如果只有部分信息,不應(yīng)該使用PUT
    DELETE:請求服務(wù)器刪除指定的頁面。
    OPTIONS:允許客戶端查看服務(wù)器的性能。

    ?

    HTTPS

    ?

    一般面試官問了你HTTP之后就會問你HTTPS了,真是一個都不能少伐?

    ?

    • HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer), 是以安全為目標(biāo)的HTTP通道,簡單講是HTTP的安全版。即HTTP下加入SSL層,HTTPS的安全基礎(chǔ)是SSL,因此加密的詳細(xì)內(nèi)容就需要SSL

    • HTTPS的通信過程,盜一張圖

      ?

      ?

    HTTPS通信過程:

  • 客戶端請求https鏈接,服務(wù)端返回公鑰

  • 客戶端產(chǎn)生隨機對稱密鑰

  • 客戶端用公鑰對對稱密鑰加密

  • 客戶端發(fā)送加密后的對稱密鑰

  • 客戶端發(fā)送通過對稱密鑰加密的密文通信

  • ?

    ===
    HTTPS與HTTP的區(qū)別:

    • 超文本傳輸協(xié)議HTTP協(xié)議被用于在Web瀏覽器和網(wǎng)站服務(wù)器之間傳遞信息。

    • HTTP協(xié)議以明文方式發(fā)送內(nèi)容,不提供任何方式的數(shù)據(jù)加密

    • HTTPS:安全套接字層超文本傳輸協(xié)議HTTPS, 在HTTP的基礎(chǔ)上加入SSL協(xié)議,SSL依靠證書來驗證服務(wù)器的身份,并為瀏覽器和服務(wù)器之間的通信加密

    • https協(xié)議需要到ca申請證書,一般免費證書很少,需要交費。

    • http是超文本傳輸協(xié)議,信息是明文傳輸,https 則是具有安全性的ssl加密傳輸協(xié)議。

    • http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。

    • http的連接很簡單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?


    ?

    兩個小問題
    1)如何保證公鑰不被篡改?
    解決方法:將公鑰放在數(shù)字證書中。只要證書是可信的,公鑰就是可信的。
    (2)公鑰加密計算量太大,如何減少耗用的時間?
    解決方法:每一次對話(session),客戶端和服務(wù)器端都生成一個”對話密鑰”(session key),用它來加密信息。由于”對話密鑰”是對稱加密,所以運算速度非常快,而服務(wù)器公鑰(非對稱加密)只用于加密”對話密鑰”本身,這樣就減少了加密運算的消耗時間。

    ?

    SSL協(xié)議

    ?

    SSL: SSL協(xié)議的基本思路是采用公鑰加密法, 采就是客戶端先向服務(wù)器端索要公鑰,然后用公鑰加密信息,服務(wù)器收到密文后,用自己的私鑰解密。

    ?

    SSL協(xié)議的基本過程如下:

    ?

  • 客戶端向服務(wù)器端索要并驗證公鑰

  • 雙方協(xié)商生成”對話密鑰”

  • 雙方采用“ 對話密鑰”進(jìn)行加密通信c

  • ?

    NSTimer面試考點

    ?

    先來說一下NSTimer在使用的時候內(nèi)存泄漏的分析

    ?

    ?

    NSTimer必須與RunLoop搭配使用,因為其定時任務(wù)的觸發(fā)基于RunLoop,NSTimer使用常見的Target-Action模式。由于RunLoop會強引用timer,timer會強引用Target,容易造成循環(huán)引用、內(nèi)存泄露等問題

    ?

    loop 強引用timer, timer 強引用 target,如果不能釋放,會造成內(nèi)存泄漏,有一個面試官問如果在target中傳入weak的self,那么可以解決循環(huán)引用問題嗎?答案是否,

    ?

    Target強引用or弱引用Timer并不是問題的關(guān)鍵,問題的關(guān)鍵是:一定要在Timer使用完畢調(diào)用invalidate使之失效(手動調(diào)用or系統(tǒng)自動調(diào)用),Timer從RunLoop中被移除并清除強引用,這個操作可打破引用1、2,而引用3是強弱引用已經(jīng)不重要了

    ?

    NSTimer一共有三種初始化方案:init開頭的普通創(chuàng)建方法、timer開頭的類工廠方法、scheduled開頭的類工廠方法。前兩者需要手動加入RunLoop中,后者會自動加入當(dāng)前RunLoop的DefaultMode中

    ?

    以上我只是整理說了一些核心的點,其他部分可閱讀這里

    ?

    對于NSTimer,面試官還會問,它是否是時間準(zhǔn)確呢?大家可能都知道是時間不準(zhǔn)確的,因為受RunLoop的影響,那么GCD中也有延時,如果用GCD來做延時,那時間準(zhǔn)確嗎?

    ?

    答案是GCD的time是準(zhǔn)確的,GCD 的線程管理是通過系統(tǒng)來直接管理的。GCD Timer 是通過 dispatch port 給 RunLoop 發(fā)送消息,來使 RunLoop 執(zhí)行相應(yīng)的 block,如果所在線程沒有 RunLoop,那么 GCD 會臨時創(chuàng)建一個線程去執(zhí)行 block,執(zhí)行完之后再銷毀掉,因此 GCD 的 Timer 是不依賴 RunLoop 的。

    ?

    KVC和KVO

    ?

    在這里只說一個問題,kvo 里面什么時候修改屬性的stter方法的?
    中間類在被觀察的屬性的setter方法中,在改變屬性值的前后分別添加了willChangeValueForKey:和didChangeValueForKey:。使其在通過KVC標(biāo)準(zhǔn)改變屬性值時可以被觀察到,并向觀察者發(fā)送消息。

    ?

    AFNetworking的工作原理,2.0和3.0的線程區(qū)別?

    ?

    AFNetworking 2.0 線程 ?使用的是常駐線程,自己創(chuàng)建線程并添加到runloop中,AFN每次進(jìn)行的網(wǎng)絡(luò)操作,開始、暫停、取消操作時都將相應(yīng)的執(zhí)行任務(wù)扔進(jìn)了自己創(chuàng)建的線程的 RunLoop 中進(jìn)行處理,從而避免造成主線程的阻塞。

    ?

    ?

    每一個請求對應(yīng)一個AFHTTPRequestOperation實例對象(以下簡稱operation),每一個operation在初始化完成后都會被添加到一個NSOperationQueue中。由這個NSOperationQueue來控制并發(fā),系統(tǒng)會根據(jù)當(dāng)前可用的核心數(shù)以及負(fù)載情況動態(tài)地調(diào)整最大的并發(fā) operation 數(shù)量,我們也可以通過setMaxConcurrentoperationCount:方法來設(shè)置最大并發(fā)數(shù)。注意:并發(fā)數(shù)并不等于所開辟的線程數(shù)。具體開辟幾條線程由系統(tǒng)決定。
    也就是說此處執(zhí)行operation是并發(fā)的、多線程的。

    ?


    ?

    AF中常駐線程的實現(xiàn)

    ?

  • 使用單例創(chuàng)建線程

  • 添加到runloop中,且加了一個NSMachPort,來防止這個新建的線程由于沒有活動直接退出。【 使用MachPort配合RunLoop進(jìn)行線程保活】

  • ?

    AF3.x為什么不再需要常駐線程?
    NSURLConnection的一大痛點就是:發(fā)起請求后,這條線程并不能隨風(fēng)而去,而需要一直處于等待回調(diào)的狀態(tài)。
    NSURLSession發(fā)起的請求,不再需要在當(dāng)前線程進(jìn)行代理方法的回調(diào)!可以指定回調(diào)的delegateQueue,這樣我們就不用為了等待代理回調(diào)方法而苦苦保活線程了。
    同時還要注意一下,指定的用于接收回調(diào)的Queue的maxConcurrentOperationCount設(shè)為了1,這里目的是想要讓并發(fā)的請求串行的進(jìn)行回調(diào)。
    為什么要串行回調(diào)?

    ?

    ?

    ?

    -?(AFURLSessionManagerTaskDelegate?*)delegateForTask:(NSURLSessionTask?*)task?{NSParameterAssert(task);AFURLSessionManagerTaskDelegate?*delegate?=?nil;[self.lock?lock];//給所要訪問的資源加鎖,防止造成數(shù)據(jù)混亂delegate?=?self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)];[self.lock?unlock];return?delegate; }

    ?

    ?

    這邊對 self.mutableTaskDelegatesKeyedByTaskIdentifier 的訪問進(jìn)行了加鎖,目的是保證多線程環(huán)境下的數(shù)據(jù)安全
    面試官可能會問你:為什么AF3.0中需要設(shè)置self.operationQueue.maxConcurrentOperationCount = 1;而AF2.0卻不需要?
    —>>>
    AF3.0的operationQueue是用來接收NSURLSessionDelegate回調(diào)的,鑒于一些多線程數(shù)據(jù)訪問的安全性考慮,設(shè)置了maxConcurrentOperationCount = 1來達(dá)到串行回調(diào)的效果

    ?

    —>>>
    AF2.0的operationQueue是用來添加operation并進(jìn)行并發(fā)請求的,所以不要設(shè)置為1。

    ?

    MRC環(huán)境下在assign、retain、copy下屬性的set方法

    ?

    直接上代碼了–>>

    ?

    ?

    ?

    ?

    //assign環(huán)境下 -(void)setName:(NSString?*)name{_name?=?name; } //retain環(huán)境下 -(void)setName:(NSString?*)name{if?(_name?!=?name)?{[_name?release];_name?=?[name?retain];} } //copy環(huán)境下 -(void)setName:(NSString?*)name{if?(_name?!=?name)?{[_name?release];_name?=?[name?copy];} }

    ?

    ?

    深拷貝,淺拷貝

    ?

    • 淺copy,類似strong,持有原始對象的指針,會使retainCount加一。

    • 深copy,會創(chuàng)建一個新的對象,不會對原始對象的retainCount變化。
      面試官可能會問,如果對一個可變數(shù)組進(jìn)行深拷貝,則會對可變數(shù)組里面的元素也會進(jìn)行重新復(fù)制一份嗎?答:不會,深拷貝,可變數(shù)組就是一個箱子,如果進(jìn)行深拷貝,則會再拷貝出一個新的箱子,但箱子里面的元素不會拷貝出新的。

    ?

    iOS中的幾種鎖

    ?

    互斥鎖
    用于多線程編程,防止兩條線程同時對同一公共資源進(jìn)行讀寫的機制。NSLock,pthread_mutex, @synchronized

    ?

    遞歸鎖
    遞歸鎖有一個特點,就是同一個線程可以加鎖N次而不會引發(fā)死鎖。
    NSRecursiveLock, 2.pthread_mutex(recursive):

    ?

    自旋鎖:
    是用于多線程同步的一種鎖,線程反復(fù)檢查鎖變量是否可用。由于線程在這一過程中保持執(zhí)行,因此是一種忙等待。一旦獲取了自旋鎖,線程會一直保持該鎖,直至顯式釋放自旋鎖。
    OSSpinLock

    ?

    信號量:一種同步方式
    信號量可以有更多的取值空間,用來實現(xiàn)更加復(fù)雜的同步,而不單單是線程間互斥。
    dispatch_semaphore:

    ?

    條件鎖:
    就是條件變量,當(dāng)進(jìn)程的某些資源要求不滿足時就進(jìn)入休眠,也就是鎖住了。當(dāng)資源被分配到了,條件鎖打開,進(jìn)程繼續(xù)運行。
    NSCondition, NSConditionLock


    遵循NSLocking協(xié)議,使用的時候同樣是lock,unlock加解鎖,wait是傻等,waitUntilDate:方法是等一會,都會阻塞掉線程,signal是喚起一個在等待的線程,broadcast是廣播全部喚起。

    ?

    讀寫鎖:

    ?

    ?

    ?

    //加讀鎖 pthread_rwlock_rdlock(&rwlock); //解鎖 pthread_rwlock_unlock(&rwlock); //加寫鎖 pthread_rwlock_wrlock(&rwlock); //解鎖 pthread_rwlock_unlock(&rwlock);

    ?

    ?

    @synchronized結(jié)構(gòu)在工作時為傳入的對象分配了一個遞歸鎖,其他內(nèi)容可參閱文檔

    ?

    SDWebImage 緩存原理

    ?

    對于常用的三方庫,一般面試官都會問到,因為篇幅較長,我只說一些比較核心的點,

    ?

    • SDWebImage 使用的是NSCache進(jìn)行緩存的,為什么用NSCache進(jìn)行緩存呢,

    ?

    ?

    ?

    int?main(int?argc,?const?char?*?argv[])?{@autoreleasepool?{//創(chuàng)建一個NSCache緩存對象NSCache?*cache?=?[[NSCache?alloc]?init];//設(shè)置緩存中的對象個數(shù)最大為5個[cache?setCountLimit:5];//創(chuàng)建一個CacheTest類作為NSCache對象的代理CacheTest?*ct?=?[[CacheTest?alloc]?init];//設(shè)置代理cache.delegate?=?ct;//創(chuàng)建一個字符串類型的對象添加進(jìn)緩存中,其中key為TestNSString?*test?=?@"Hello,?World";[cache?setObject:test?forKey:@"Test"];//遍歷十次用于添加for?(int?i?=?0;?i?<?10;?i++){[cache?setObject:[NSString?stringWithFormat:@"Hello%d",?i]?forKey:[NSString?stringWithFormat:@"World%d",?i]];NSLog(@"Add?key:%@??value:%@?to?Cache",?[NSString?stringWithFormat:@"Hello%d",?i],?[NSString?stringWithFormat:@"World%d",?i]);}for?(int?i?=?0;?i?<?10;?i++){NSLog(@"Get?value:%@?for?key:%@",?[cache?objectForKey:[NSString?stringWithFormat:@"World%d",?i]],?[NSString?stringWithFormat:@"World%d",?i]);}[cache?removeAllObjects];for?(int?i?=?0;?i?<?10;?i++){NSLog(@"Get?value:%@?for?key:%@",?[cache?objectForKey:[NSString?stringWithFormat:@"World%d",?i]],?[NSString?stringWithFormat:@"World%d",?i]);}NSLog(@"Test?%@",?test);}return?0; }

    ?

    ?

    上面的代碼創(chuàng)建了一個NSCache對象,設(shè)置了其最大可緩存對象的個數(shù)為5個,當(dāng)我們要添加第六個對象時NSCache自動刪除了我們添加的第一個對象并觸發(fā)了NSCacheDelegate的回調(diào)方法,

    添加第七個時也是同樣的,刪除了緩存中的一個對象才能添加進(jìn)去,一下情況NSCache會刪除緩存:
    ? ? NSCache緩存對象自身被釋放
    ? ? 手動調(diào)用removeObjectForKey:方法
    ? ? 手動調(diào)用removeAllObjects
    ? ? 緩存中對象的個數(shù)大于countLimit,或,緩存中對象的總cost值大于totalCostLimit
    ? ? 程序進(jìn)入后臺后
    ? ? 收到系統(tǒng)的內(nèi)存警告

    ?


    ?

    異步方式在ioQueue上執(zhí)行刪除操作,所有IO操作使用一個串行隊列來執(zhí)行,避免加鎖釋放鎖的復(fù)雜,還有就是使用NSOperation作為一個標(biāo)識用來取消耗時的磁盤查詢?nèi)蝿?wù)。內(nèi)存緩存就直接刪除NSCache對象的數(shù)據(jù),磁盤緩存就直接獲取文件的絕對路徑后刪除即可

    ?

    ?

    ?

    if?(fromDisk)?{//異步方式在ioQueue上執(zhí)行刪除操作dispatch_async(self.ioQueue,?^{//使用key構(gòu)造一個默認(rèn)路徑下的文件存儲的絕對路徑//調(diào)用NSFileManager刪除該路徑的文件[_fileManager?removeItemAtPath:[self?defaultCachePathForKey:key]?error:nil];//有回調(diào)塊就在主線程中執(zhí)行if?(completion)?{dispatch_async(dispatch_get_main_queue(),?^{completion();});}});//不需要刪除磁盤數(shù)據(jù)并且有回調(diào)塊就直接執(zhí)行}?else?if?(completion){completion();}

    ?

    刪除磁盤中過期的圖片,以及當(dāng)緩存大小大于配置的值時,進(jìn)行緩存清理

    ?

    ?

    ?

    -?(void)backgroundDeleteOldFiles?{Class?UIApplicationClass?=?NSClassFromString(@"UIApplication");if(!UIApplicationClass?||?![UIApplicationClass?respondsToSelector:@selector(sharedApplication)])?{return;}UIApplication?*application?=?[UIApplication?performSelector:@selector(sharedApplication)];__block?UIBackgroundTaskIdentifier?bgTask?=?[application?beginBackgroundTaskWithExpirationHandler:^{//?Clean?up?any?unfinished?task?business?by?marking?where?you//?stopped?or?ending?the?task?outright.[application?endBackgroundTask:bgTask];bgTask?=?UIBackgroundTaskInvalid;}];//?Start?the?long-running?task?and?return?immediately.[self?deleteOldFilesWithCompletionBlock:^{[application?endBackgroundTask:bgTask];bgTask?=?UIBackgroundTaskInvalid;}]; }

    ?

    多線程

    ?

    iOS中有哪些多線程方案?

    ?

    常用的有三種: NSThread NSOperationQueue GCD

    ?

    ?

    ?

    ?

    1、NSThread?是這三種范式里面相對輕量級的,但也是使用起來最負(fù)責(zé)的, 你需要自己管理thread的生命周期,線程之間的同步。線程共享同一應(yīng)用程序的部分內(nèi)存空間, 它們擁有對數(shù)據(jù)相同的訪問權(quán)限。你得協(xié)調(diào)多個線程對同一數(shù)據(jù)的訪問, 一般做法是在訪問之前加鎖,這會導(dǎo)致一定的性能開銷。2、NSOperationQueue?以面向?qū)ο蟮姆绞椒庋b了用戶需要執(zhí)行的操作, 我們只要聚焦于我們需要做的事情,而不必太操心線程的管理,同步等事情, 因為NSOperation已經(jīng)為我們封裝了這些事情。 NSOperation 是一個抽象基類,我們必須使用它的子類。3、?GCD:?iOS4?才開始支持,它提供了一些新的特性,以及運行庫來支持多核并行編程, 它的關(guān)注點更高:如何在多個cpu上提升效率。總結(jié): -?NSThread是早期的多線程解決方案,實際上是把C語言的PThread線程管理代碼封裝成OC代碼。 -?GCD是取代NSThread的多線程技術(shù),C語法+block。功能強大。 -?NSOperationQueue是把GCD封裝為OC語法,額外比GCD增加了幾項新功能。*?最大線程并發(fā)數(shù)*?取消隊列中的任務(wù)*?暫停隊列中的任務(wù)*?可以調(diào)整隊列中的任務(wù)執(zhí)行順序,通過優(yōu)先級*?線程依賴*?NSOperationQueue支持KVO。這就意味著你可以觀察任務(wù)的狀態(tài)屬性。 但是NSOperationQueue的執(zhí)行效率沒有GCD高,所以一半情況下,我們使用GCD來完成多線程操作。

    ?

    ?

    面試題:多個網(wǎng)絡(luò)請求完成后執(zhí)行下一步?

    第一種方式:使用dispatch_group

    ?

    ?

    ?

    ?

    -(void)Btn2{NSString?*str?=?@"http://www.swifty.cc/p/6930f335adba";NSURL?*url?=?[NSURL?URLWithString:str];NSURLRequest?*request?=?[NSURLRequest?requestWithURL:url];NSURLSession?*session?=?[NSURLSession?sharedSession];dispatch_group_t?downloadGroup?=?dispatch_group_create();for?(int?i=0;?i<10;?i++)?{dispatch_group_enter(downloadGroup);NSURLSessionDataTask?*task?=?[session?dataTaskWithRequest:request?completionHandler:^(NSData?*?_Nullable?data,?NSURLResponse?*?_Nullable?response,?NSError?*?_Nullable?error)?{NSLog(@"%d---%d",i,i);dispatch_group_leave(downloadGroup);}];[task?resume];}dispatch_group_notify(downloadGroup,?dispatch_get_main_queue(),?^{NSLog(@"end");}); }

    ?

    ?

    創(chuàng)建一個dispatch_group_t, 每次網(wǎng)絡(luò)請求前先dispatch_group_enter,請求回調(diào)后再dispatch_group_leave,對于enter和leave必須配合使用,有幾次enter就要有幾次leave,否則group會一直存在。當(dāng)所有enter的block都leave后,會執(zhí)行dispatch_group_notify的block。

    ?

    第二種方式可以采用信號量dispatch_semaphore_t

    ?

    ?

    ?

    ?

    -(void)Btn3{NSString?*str?=?@"http://www.swifty.cc/p/6930f335adba";NSURL?*url?=?[NSURL?URLWithString:str];NSURLRequest?*request?=?[NSURLRequest?requestWithURL:url];NSURLSession?*session?=?[NSURLSession?sharedSession];dispatch_semaphore_t?sem?=?dispatch_semaphore_create(0);for?(int?i=0;?i<10;?i++)?{NSURLSessionDataTask?*task?=?[session?dataTaskWithRequest:request?completionHandler:^(NSData?*?_Nullable?data,?NSURLResponse?*?_Nullable?response,?NSError?*?_Nullable?error)?{NSLog(@"%d---%d",i,i);count++;if?(count==10)?{dispatch_semaphore_signal(sem);count?=?0;}}];[task?resume];}dispatch_semaphore_wait(sem,?DISPATCH_TIME_FOREVER);dispatch_async(dispatch_get_main_queue(),?^{NSLog(@"end");}); }

    ?

    ?

    dispatch_semaphore信號量為基于計數(shù)器的一種多線程同步機制。如果semaphore計數(shù)大于等于1,計數(shù)-1,返回,程序繼續(xù)運行。如果計數(shù)為0,則等待。dispatch_semaphore_signal(semaphore)為計數(shù)+1操作,dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)為設(shè)置等待時間,這里設(shè)置的等待時間是一直等待。
    對于以上代碼通俗一點就是,開始為0,等待,等10個網(wǎng)絡(luò)請求都完成了,dispatch_semaphore_signal(semaphore)為計數(shù)+1,然后計數(shù)-1返回,程序繼續(xù)執(zhí)行。(這里也就是為什么有個count變量的原因,記錄網(wǎng)絡(luò)回調(diào)的次數(shù),回調(diào)10次之后再發(fā)信號量,使后面程序繼續(xù)運行)。

    ?

    什么是dispatch_barrier_async(柵欄函數(shù))?

    ?

    ?

    ?

    ?

    dispatch_barrier_sync(dispatch_queue_t???queue,?^{})

    ?

    ?

    • 在它前面的任務(wù)執(zhí)行結(jié)束后它才執(zhí)行,它后面的任務(wù)要等它執(zhí)行完成后才會開始執(zhí)行,

    • 避免數(shù)據(jù)競爭

    ?

    sync和async
    sync:同于當(dāng)前線程, 可以是主線程也可以是子線程
    async:就是不同于當(dāng)前線程, 可以是主線程也可以是子線程

    ?

    XMPP是什么?XMPP進(jìn)行傳輸時,需要傳大量的數(shù)據(jù),如何減少數(shù)據(jù)?

    ?

    XMPP:
    1)XMPP 是一種基于XML的協(xié)議,XMPP是一個分散型通信網(wǎng)絡(luò)
    2)XMPP是一種基于標(biāo)準(zhǔn)通用標(biāo)記語言的子集XML的協(xié)議,它繼承了在XML環(huán)境中靈活的發(fā)展性,XMPP有超強的擴展性。XMPP中定義了三個角色,客戶端,服務(wù)端,網(wǎng)關(guān)。通信能夠在這個三者的任意兩個之間雙向發(fā)生,而他們的傳輸是XML流
    3)XMPP工作原理:所有從一個客戶端到另一個客戶端的消息和數(shù)據(jù)都要通過服務(wù)端
    4)XMPP允許建立并行的TCP套接字鏈接對所有連接上的客戶端和服務(wù)器端。持久的套接字的連接使得XMPP能夠更有效的支持高級的具有存在能力的應(yīng)用在帶寬和處理資源的使用中。

    ?

    小結(jié):
    而XMPP的核心部分就是一個在網(wǎng)絡(luò)上分片斷發(fā)送XML的流協(xié)議。這個流協(xié)議是XMPP的即時通訊指令的傳遞基礎(chǔ),也是一個非常重要的可以被進(jìn)一步利用的網(wǎng)絡(luò)基礎(chǔ)協(xié)議。所以可以說,XMPP用TCP傳的是XML流。

    ?

    =======
    如何減少數(shù)據(jù)?

    ?

  • 如果是大量的數(shù)據(jù),對于XML,需要對傳的信息進(jìn)行簡化,比如command, message中的信息要簡化,

  • 使用別的數(shù)據(jù)傳輸協(xié)議,比如protocol Buff(可以傳輸binary 二進(jìn)制數(shù)據(jù)),格式可以用json

  • ?

    Swift問題

    ?

    swift語言和OC語言的本質(zhì)區(qū)別是什么?

    答:本質(zhì)區(qū)別是Swift是靜態(tài)語言,而OC是動態(tài)語言,面試回去路上,才想到問題的最好的答案—-

    ?

    問題:子類不能重寫父類的extension的方法?怎么解決呢?

    解決方法如下:

    ?

    ?

    ?

    ?

    //父類中 @objc?extension?MOBBaseViewController?{//要重寫的方法public?func?testExt()?{print("----------");}}----- //子類中 import?UIKitclass?MOBClassifyViewController:?MOBBaseViewController?{override?func?viewDidLoad()?{super.viewDidLoad()//?Do?any?additional?setup?after?loading?the?view.}//重寫父類extension方法override?func?testExt(){print(">>>>>>>>>>>>")}}

    ?

    ?

    因為extension中的方法是私有的,so子類訪問不到,因此要用public修飾下,@objc有以下兩點說明:
    ? ? fileprivate 或者 private 保證方法私有 能在同一個類 或者 同一個文件(extension)中訪問這個方法 如果定義為private 那么只能在一個類中訪問 不能在類擴展中訪問
    ? ? 允許這個函數(shù)在“運行時”通過oc的消息機制調(diào)用

    ?

    NSString跟Swift String的區(qū)別和使用場景

    ?

    NSString和String的共同點

    • String保留了大部分NSString的api比如
      .hasPrefix
      .lowercaseString
      .componentsSeparatedByString
      .substringWithRange 等等
      所以很多常規(guī)操作在開發(fā)中使用兩者之一都是可以的,

    ?

    NSString和String的不同點

    • NSString是引用類型。Swift String是值類型

    ?

    ?

    ?

    ?

    ?

    var?nsString:?NSString?=?NSString()var?swiftString:String?=?String()????????var?nsString:?NSString?=?"dsx"var?swiftString:String?=?"dsx"

    ?

    ?

    兩者都可以使用自己的類名來直接進(jìn)行初始化,下面的方法也是初始化,雖然寫法相同,但是NSString的意思是初始化了一個指針指向了這個字符串,但Swift String的意思則是把字符串字面量賦值給變量

    ?

    • NSString需要用append或者stringWithFormat將兩個字符串拼接,Swift String只需要用 + 即可

    • Swift String 可以實現(xiàn)字符串遍歷

    ?

    ?

    ?

    for?character?in?"My?name?is?dsx".characters?{print(character) }

    ?

    ?

    • 計算字符串長度,NSString直接使用 字符串.length 就可以獲得字符串的長度,swift真正的類似于.length的方法就是取出characters屬性(數(shù)組)然后.count

    • 比較字符串相等的方式

    ?

    ?

    ?

    et?strA:?NSString?=?"" let?strB:?NSString?=?"" let?strC:?NSString?=?"dsx" let?strD:?NSString?=?"dsx"//?NSString?字符串相等 if(strA.isEqualToString(strB?as?String)){print("yes"); }//?String的相等??? if?(strC?==?strD){print("yes"); }

    ?

    ?

    • NSString可以同基本數(shù)據(jù)類型見轉(zhuǎn)化

    var?strA:?NSString?=?"12306" var?strB:?NSString?=?"0.618"?? var?numOfInt???????=?strA.integerValue; var?numOfDouble????=?strB.doubleValue;

    ?

    • String可以通過isEmpty屬性來判斷該字符串是否為空,是string獨有的

    • String獨有的字符串插入字符功能

    ?

    ?

    ?

    var?strA:String?=?"My?name?is?dx" strA.insert("s",?atIndex:?strA.characters.indexOf("x")!); print(strA)?//?My?name?is?dsx

    ?

    ?

    僅僅可以插入單個字符不能插字符串,如果里面寫成ss 就會報錯Cannot convert value of type 'String' to expected argument type 'Character'

    ?

    作者:天下林子

    作為一個開發(fā)者,有一個學(xué)習(xí)的氛圍跟一個交流圈子特別重要這是一個我的iOS交流群:869685378,不管你是小白還是大牛歡迎入駐 ,分享BAT,阿里面試題、面試經(jīng)驗,討論技術(shù), 大家一起交流學(xué)習(xí)成長!

    ?

    總結(jié)

    以上是生活随笔為你收集整理的iOS 开发者 2019 面试总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。