iOS阿里三面之面試題整理

1、dSYM你是如何分析的

方法1 使用XCode
這種方法可能是最容易的方法了。

要使用Xcode符號化 crash log,你需要下面所列的3個文件:
crash報告(.crash文件)
符號文件 (.dsymb文件)
應用程序文件 (appName.app文件,把IPA文件后綴改為zip,然后解壓,Payload目錄下的appName.app文件), 這里的appName是你的應用程序的名稱。
把這3個文件放到同一個目錄下,打開Xcode的Window菜單下的organizer,然后點擊Devices tab,然后選中左邊的Device Logs。
然后把.crash文件拖到Device Logs或者選擇下面的import導入.crash文件。
這樣你就可以看到crash的詳細log了。
方法2 使用命令行工具symbolicatecrash
有時候Xcode不能夠很好的符號化crash文件。我們這里介紹如何通過symbolicatecrash來手動符號化crash log。
在處理之前,請依然將“.app“, “.dSYM”和 ".crash"文件放到同一個目錄下。現在打開終端(Terminal)然后輸入如下的命令:
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
然后輸入命令:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash appName.crash appName.app > appName.log
現在,符號化的crash log就保存在appName.log中了。
方法3 使用命令行工具atos
如果你有多個“.ipa”文件,多個".dSYMB"文件,你并不太確定到底“dSYMB”文件對應哪個".ipa"文件,那么,這個方法就非常適合你。
特別當你的應用發布到多個渠道的時候,你需要對不同渠道的crash文件,寫一個自動化的分析腳本的時候,這個方法就極其有用。
具體方法 請百度
本文分析了拿到用戶的.crash文件之后,如何符合化crash文件的3種方法,分別有其適用場景,方法3適用于自動化crash文件的分析。

2.多線程有哪幾種?你更傾向于哪一種?

NSThread Cocoa NSOperation (使用NSOperation和NSOperationQueue) GCD (Grand Central Dispatch)

1.NSThread:(兩種創建方式)

[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];

NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];

[myThread start];
優點:NSThread 比其他兩個輕量級。 缺點:需要自己管理線程的生命周期,線程同步,線程同步時對數據的加鎖會有一定的系統開銷。

2.Cocoa Operation

NSOperationQueue*oprationQueue= [[NSOperationQueuealloc] init];

oprationQueueaddOperationWithBlock:^{

//這個block語句塊在子線程中執行

}
優點:不需要關心線程管理,數據同步的事情。 Cocoa Operation 相關的類是 NSOperation ,NSOperationQueue。NSOperation是個抽象類,使用它必須用它的子類,可以實現它或者使用它定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation。創建NSOperation子類的對象,把對象添加到NSOperationQueue隊列里執行,我們會把我們的執行操作放在NSOperation中main函數中。

3.GCD

Grand Central Dispatch (GCD)是Apple開發的一個多核編程的解決方法,GCD是一個替代諸如NSThread, NSOperationQueue, NSInvocationOperation等技術的很高效和強大的技術。它讓程序平行排隊的特定任務,根據可用的處理資源,安排他們在任何可用的處理器核心上執行任務,一個任務可以是一個函數(function)或者是一個block。 dispatch queue分為下面三種: private dispatch queues,同時只執行一個任務,通常用于同步訪問特定的資源或數據。 global dispatch queue,可以并發地執行多個任務,但是執行完成的順序是隨機的。 Main dispatch queue 它是在應用程序主線程上執行任務的。 GCD 掃盲篇;

3、單利的弊端

優點:
1:一個類只被實例化一次,提供了對唯一實例的受控訪問。
2:節省系統資源
3:允許可變數目的實例。
缺點:
1:一個類只有一個對象,可能造成責任過重,在一定程度上違背了“單一職責原則”。
2:由于單利模式中沒有抽象層,因此單例類的擴展有很大的困難。
3:濫用單例將帶來一些負面問題,如為了節省資源將數據庫連接池對象設計為的單例類,可能會導致共享連接池對象的程序過多而出現連接池溢出;如果實例化的對象長時間不被利用,系統會認為是垃圾而被回收,這將導致對象狀態的丟失。

4、如何把異步線程轉換成同步任務進行單元測試?

參考此篇博客 里面的信號量的解釋,Dispatch Semaphore 信號量 在項目中的應用:強制把異步任務轉換為同步任務來方便進行單元測試

5、介紹下App啟動的完成過程?

①.先加載Main函數

②.在Main函數里的 UIApplicationMain方法中,創建Application對象 創建Application的Delegate對象

③.創建主循環,代理對象開始監聽事件

④.啟動完畢會調用 didFinishLaunching方法,并在這個方法中創建UIWindow

⑤.設置UIWindow的根控制器是誰

⑥.如果有storyboard,會根據info.plist中找到應用程序的入口storyboard并加載箭頭所指的控制器

⑦.顯示窗口

本文考慮的時步驟③之后到步驟⑦結束時將要調用的方法

其中有AppDelegate,ViewController,MainView(控制器的View),ChildView(子控件的View)的18個方法

AppDelegate中的:
1.application:didFinishLaunchingWithOptions:

2.applicationDidBecomeActive:

ViewController中的:

3.loadView

4.viewDidLoad

5.load

6.initialize

7.viewWillAppear

8.viewWillLayoutSubviews

9.viewDidLayoutSubviews

10.viewDidAppear

MainView(控制器的View)中的:

11.initWithCoder(如果沒有storyboard就會調用initWithFrame,這里兩種方法視為一種)

12.awakeFromNib

13.layoutSubviews

14.drawRect

ChildView(子控件View)中的:

15.initWithCoder(如果沒有storyboard就會調用initWithFrame,這里兩種方法視為一種)

16.awakeFromNib

17.layoutSubviews

18.drawRect

那么問題來了,不往下看你可以把上面的十八個方法排個順序么?

  • (void)load; //這是應用程序啟動就會調用的方法,在這個方法里寫的代碼最先調用
  • (void)initialize; //這個是需要用到本類時才調用,這個方法里一般寫設置導航控制器的主題啊之類的,
    //如果在后面的方法設置導航欄主題就晚了!(當然在上面的方法里也能寫)
  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
    //這個方法里面會創建UIWindow,設置根控制器并展現,
    //比如某些應用程序要加載授權頁面也是在這加,也可以設置觀察者,監聽到通知切換根控制器
    ChildView - (instancetype)initWithCoder:(NSCoder *)aDecoder;
    //這里反正我是萬萬沒想到,childView的initwithcoder會在MainView的方法之前調用,
    //父的都還沒出來,就先整子控件? 有了解比較透徹的博友懇請告訴我謝謝。
    MainView - (instancetype)initWithCoder:(NSCoder *)aDecoder;
    // 就是關于應用程序的數據存儲后的解檔操作。
    MainView - (void)awakeFromNib;
    //在這個方法里設置view的背景等一系列普通操作,不要寫關于frame的還不準,
    //在使用IB的時候才會涉及到此方法的使用,當.nib文件被加載的時候,
    //會發送一個awakeFromNib的消息到.nib文件中的每個對象,
    //每個對象都可以定義自己的awakeFromNib函數來響應這個消息,執行一些必要的操作。
    ChildView - (void)awakeFromNib
    //子控件也有本方法,重寫父類的方法。基本用法同上
  • (void)loadView;
    //創建視圖的層次結構,這里需要注意,
    //在沒有創建控制器的view的情況下不能直接寫 self.view 因為self.view的底層是:
    if(_view == nil){
       _view = [self loadView]
    }
    //所以這么寫會直接造成死循環。
    //如果重寫這個loadView方法里面什么都不寫,會顯示黑屏。
  • (void)viewDidLoad;
    //臥槽,這個方法是用的最多的方法,但是在之后的開發中就會發現越來越不靠譜,
    //很多東西都還沒加載完畢,各種取值都不準確,很少在這里面寫東西了。
    //這里只是把視圖元件加載完成
  • (void)viewWillAppear:(BOOL)animated;
    //視圖將要出現,這個方法用的非常多,比如如果要設置導航欄的setNavigationBarHiden:animate:
    //就必須要在這里寫,才能完美契合,不卡跳。 還有很多比如監聽屏幕旋轉啦,

//viewWillTransitionToSize:可能要在本方法里再調一次,
//或者就是新到這個界面要reloadData或是自動下拉刷新等 都是寫在本方法里

  • (void)viewWillLayoutSubviews;
    //視圖將要布局子視圖,蘋果建議的設置界面布局屬性的方法,
    //這個方法和viewWillAppear里,系統的底層都是沒有寫任何代碼的,也就是說這里面不寫super 也是可以的
    MainView - (void)layoutSubviews;
    //在這個方法里一般設置子控件的frame,因為這里相當于是布局基本完成了,
    //設置時取到的frame或者是self.bounds才最準,如果在awakeFromeNib里寫會不準確 。
    //還有這里要切記千萬不能把super layoutSubviews忘了,可能最后都很難找到這個bug
  • (void)viewDidLayoutSubviews;
    //這個方法我也是玩玩沒想到,控制器的view的子控件還沒有布局好呢,怎么這個控制器就已經說布局全部完成了?
    //那后邊的布局就不等了? 有獨到見解的也懇請你告訴我,這其中蘋果的意思到底是什么。
    ChildView - (void)layoutSubviews;
    //控制器的子控件里的子控件的布局就在這里寫了。
    MainView - (void)drawRect:(CGRect)rect;
    //因為默認所有額UI控件都是畫上去的,在這一步就是把所有的東西畫上去,
    //有時候需要用到Quartz2D的知識的時候都是在這個方法里話,但也是要注意別忘了寫super,
    //不然系統原本的東西就都畫不上來了,這里要建議盡可能使用貝塞爾路徑畫圖形,
    //因為系統默認的那個上下文畫法有時可能會內存泄露。drawRect方法只能在加載時調用一次,
    //如果后面還需要調用,比如下載進度的圓弧,需要一直刷幀,
    //就要使用setNeedsDisplay來定時多次調用本方法
    ChildView - (void)drawRect:(CGRect)rect;
    //view的子控件內部的畫圖方法,有時可以自己自定義label 中間帶個刪除線的(用來寫打折前的原價) 就是在這里畫根線 。
  • (void)viewDidAppear:(BOOL)animated;
    //把上面的畫圖都畫完了,這里就會顯示,視圖完全加載完成。
    //在這里的操作可能就是設置頁面的一些動畫,或者是設置tableView,collectionView,
    //QQ聊天頁面啥的滾動到底部scrollToIndexPath之類的代碼操作。
  • (void)applicationDidBecomeActive:(UIApplication *)application;
    //最后這是AppDelegate的應用程序獲取焦點方法,真正到了這里,才是所有東西全部加載完畢,應用程序整裝待發保持最佳狀態等待用戶操作。
    //這個方法中一般會寫關于彈出鍵盤的方法,比如有的用戶登錄界面為了更好的用戶體驗,
    //就讓你在剛打開程序來到登錄界面的時候,光標的焦點就自動在賬號的文本框里閃爍,
    //也就是設置賬號文本框為第一響應者。鍵盤在頁面加載完畢后從下方彈出,這種代碼一般就在本方法寫。

6、比如App啟動過慢,你可能想到的因素有哪些?

  1. App啟動過程
    解析Info.plist
    加載相關信息,例如如閃屏
    沙箱建立、權限檢查
    Mach-O加載
    如果是胖二進制文件,尋找合適當前CPU類別的部分
    加載所有依賴的Mach-O文件(遞歸調用Mach-O加載的方法)
    定位內部、外部指針引用,例如字符串、函數等
    執行聲明為attribute((constructor))的C函數
    加載類擴展(Category)中的方法
    C++靜態對象加載、調用ObjC的 +load 函數
    程序執行
    調用main()
    調用UIApplicationMain()
    調用applicationWillFinishLaunching
    2、影響啟動性能的因素
    main()函數之前耗時的影響因素
    動態庫加載越多,啟動越慢。
    ObjC類越多,啟動越慢
    C的constructor函數越多,啟動越慢
    C++靜態對象越多,啟動越慢
    ObjC的+load越多,啟動越慢
    main()函數之后耗時的影響因素
    執行main()函數的耗時
    執行applicationWillFinishLaunching的耗時
    rootViewController及其childViewController的加載、view及其subviews的加載
    另外參考一下今日頭條的啟動優化方案

針對于今日頭條這個App我們可以優化的點如下:

純代碼方式而不是storyboard加載首頁UI。
對didFinishLaunching里的函數考慮能否挖掘可以延遲加載或者懶加載,需要與各個業務方pm和rd共同check 對于一些已經下線的業務,刪減冗余代碼。
對于一些與UI展示無關的業務,如微博認證過期檢查、圖片最大緩存空間設置等做延遲加載。
對實現了+load()方法的類進行分析,盡量將load里的代碼延后調用。
上面統計數據顯示展示feed的導航控制器頁面(NewsListViewController)比較耗時,對于viewDidLoad以及viewWillAppear方法中盡量去嘗試少做,晚做,不做。

7、0x8badf00d表示是什么?

看門狗超時,在iOS上,它經常出現在執行一個同步網絡調用而阻塞主線程的情況。因此,永遠不要進行同步網絡調用。

8、怎么防止反編譯?

本地數據加密。
iOS應用防反編譯加密技術之一:對NSUserDefaults,sqlite存儲文件數據加密,保護帳號和關鍵信息

URL編碼加密。
iOS應用防反編譯加密技術之二:對程序中出現的URL進行編碼加密,防止URL被靜態分析

網絡傳輸數據加密。
iOS應用防反編譯加密技術之三:對客戶端傳輸數據提供加密方案,有效防止通過網絡接口的攔截獲取數據

方法體,方法名高級混淆。
iOS應用防反編譯加密技術之四:對應用程序的方法名和方法體進行混淆,保證源碼被逆向后無法解析代碼

程序結構混排加密。
iOS應用防反編譯加密技術之五:對應用程序邏輯結構進行打亂混排,保證源碼可讀性降到最低

其實我覺得大可不必,本身反編譯成本就很大,代碼這么多,一個個反編譯過來是在蛋疼,就算有偽代碼也需要理解,而且有些代碼就算有偽代碼也很難理解。

只要做好核心代碼,做好混淆就行了,比如涉及到密碼,核心算法。

9、說說你遇到的技術難點并如何解決的?

一般這種問題的時候,面試官是想通過你講解你遇到的是什么類型的問題,然后是怎么解決的方案來判斷你的知識層面。值得注意的一點是,往往不少同學在回答這道問題講如何解決的時候會說:首先通過Google、百度等搜索尋找解決方案,2、問群里。。。等等之類的答案。敲黑板啦~~注意啦,同學們,人家要的不是這個答案好嗎?雖然你這么答也不算是錯,只是理解有偏差,但起不到加分的結果。所以在面試之前,各位同學應該好好的想想這個問題的答案,當然每個人遇到的難點都不大相同,涉及到的技術層面也不一樣,這也是這個問題的目的所在。

10、說說你了解的第三方原理或底層知識?

作為一個開發者,有一個學習的氛圍和一個交流圈子特別重要,這是我的交流群(123),大家有興趣可以進群里一起交流學習
另附上一份大廠面試題合集,進群可自行下載!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容