大江東去
天下大勢,合久必分,分久必合,如今這iOS的行情就是從波峰到波谷,從波谷又趨于穩定,最近小編因為任性離職了,找了兩個星期的工作,頗有一番心得,希望與諸君共勉,一起度過這互聯網的寒冬期,走向人生巔峰!
從目前iOS目前形勢來看,相對去年略有回暖,最近面試,基本上每天兩三家,從數量上看,還是可觀的,但是這并不意味工作好找,現在找工作難度不斷上漲,市場注定會淘汰一批渾水摸魚之輩,你是否是其中的一個,那就要問蒼天了!
既然選擇了這個行業,再沒有轉行或者單飛之前,那就好好堅持下去,沒事多啃啃博客,沒事多敲敲代碼,該熬夜還得熬夜,該加班還得加班,不要拿健康,生命第一
去第一家公司面試,毫無準備就去了,結果是碰了一鼻子灰,當初以為面試官問的問題問得很難,但是現在想來,也屬于一個常問的面試題,多線程的用法
當a,b,c,d四個線程,a,b,c執行完的結果,將作為d的一個參數傳入,怎么實現? (個人覺得這個問題這是一個道非常好的面試題,但是小編沒有答上來,很是尷尬)
如果你說出了dispatch_group,或者隊列組這個兩個關鍵詞,那恭喜你答對了,下面是示例代碼。
/**
*? 使用dispatch_group,異步多請求
*/
- (void)asyncBaseData
{
// 全局并行隊列
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
// 創建一個group
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, globalQueue, ^{
// 執行請求1... (這里的代碼需要時同步執行才能達到效果)
});
dispatch_group_async(group, globalQueue, ^{
// 執行請求2...
});
dispatch_group_async(group, globalQueue, ^{
// 執行請求N...
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"全部請求執行完畢!");
});
}
延著這個問題基本上每個面試官都會多線程的幾種創建方式,和優缺點,這個問題必須要答對,不然面試基本可以宣布陣亡了!
ios三種多線程技術:
1.NSThread
(1)使用NSThread對象建立一個線程非常方便
(2)但是!要使用NSThread管理多個線程非常困難,不推薦使用
(3)技巧!使用[NSThread currentThread]跟蹤任務所在線程,適用于這三種技術
2.NSOperation/NSOperationQueue
(1)是使用GCD實現的一套Objective-C的API
(2)是面向對象的線程技術
(3)提供了一些在GCD中不容易實現的特性,如:限制最大并發數量、操作之間的依賴關系
3.GCD —— Grand Central Dispatch
(1)是基于C語言的底層API
(2)用Block定義任務,使用起來非常靈活便捷
(3)提供了更多的控制能力以及操作隊列中所不能使用的底層函數
第二種問題關于runtime的問題,也是面試官喜歡問的,雖然工作中可能不常用,但是面試很喜歡問,后來我發現runtime是OC的靈魂,runtime如果用得好,將會起到一勞永逸的效果。
面試官基本會問兩個問題,
什么是runtime
我們寫的代碼在程序運行過程中都會被轉化成runtime的C代碼執行,例如[target doSomething];會被轉化成objc_msgSend(target, @selector(doSomething));
你用過runtime的哪些方法,能說下他們的應用場景嗎?
這是一個見仁見智的問題,你可以說你使用過runtime的哪些方法,比如歸檔中,每個去歸檔和反歸檔,顯得步驟很重復,屬性很多的時候就是一些體力活了,如果用runtime去遍歷模型中的屬性,可以起到一勞永逸。
還有比如說,判斷某個對象是不是某個類[object isKindOfClass:[NSObject class]],這些都是runtime,舉一些你真實在項目中用過的場景,然后你可以其他的方法,也有了解過,只是不常用而已,比如說,交換方法,動態加載方法,消息轉發,動態關聯屬性。
總之,你一定要列舉你們項目中真實的應用場景,隨后列舉其他的一些方法,這樣可以突出你對此次面試準備很充足,也很真實。
MVC與MVVM,MVP設計模式的區別?
一般面試官問我這個問題,我一般都是簡單描述下MVC,然后我會說所謂MVVM,MVP都只是MVC的一個變種,延伸,多了個VM,P層,本質講,跟MVC沒什么區別,只是VM,P層,幫助C分擔了一些處理事件的壓力,相當于說一些代碼轉移到VM,P層去處理。個人覺得一般面試回答到這個份上,一般面試官都會點頭認可的。
但是有一家面試,問我有沒有使用過MVVM,可以舉一些例子嗎,你怎么設計MVVM的,當時小編就很懵逼了,后來我問了下面試官,面試官說這個跟響應式編程有關系的,我回去查了下響應式編程,這是一個比較大的話題,如果你會你可以跟面試官吹吹牛,不會的話那你可以說下場面話,這個問題暫時沒有涉獵到,回去我去查查。這樣可以顯得你是有求知欲的人。
這個問題問完,一般會問你用過哪些設計模式?
這個問題,個人覺得得看面試官的角色,如果面試官不是iOS開發面試,那么這個問題,你可以答得越詳細越好,比如你用過哪些設計模式,在項目中應用場景,這個問題小編覺得是一個比較簡單的問題了,如果這個問題答不好,那么你可能就需要去黑木崖面壁思過了!
不過昨天念念信息面試,面試官問到工廠模式,這個倒是有點出乎我的意料,后來我去查了下,發現工廠模式還是有必要去好哈掌握下。
OS中工廠模式我的理解是:利用OC語言的特性“多態”來創建不同的對象
如果后臺提供的一個接口中有兩至三種不同的數據,比如說有些是新聞,有些是圖片,有些是音樂,那么該如非常方便的去使用這些數據在頁面上展示出來呢?
在這里舉個簡單的例子:
先創建一個BaseModel,然后再News,Music,Images繼承于BaseModel,然后在BaseModel中寫一個便利構造器:
//創建一個便利構造器+ (instancetype)initWithDictionary:(NSDictionary*)dictionary;
// 根據字典內提供的數據分別創建出對應的model來獲取數據+ (instancetype)initWithDictionary:(NSDictionary *)dictionary{// 先使用當前類(父類)創建出model對象BaseModel *model= nil;// 根據字典中key對應的數據初始化不同的子類對象并將其返回給我們的父類
if([dictionary[@"tag"] isEqualToString:@"news"]) {model= [[News alloc] init];? ? }elseif([dictionary[@"tag"] isEqualToString:@"images"]){model= [[Images alloc] init];? ? }elseif([dictionary[@"tag"] isEqualToString:@"music"]){model= [[Music alloc] init];? ? }? ? [modelsetValuesForKeysWithDictionary:dictionary];? ? returnmodel;}
這里直接使用plist文件寫一些死數據來展示,那么在tableView中的展示數組該如何獲取值呢?
- (NSMutableArray*)dataArray{if(!_dataArray)? ? {? ? ? ? _dataArray = [NSMutableArrayarray];NSString*path = [[NSBundlemainBundle] pathForResource:@"data"ofType:@"plist"];NSArray*arr = [NSArrayarrayWithContentsOfFile:path];for(NSDictionary*dicinarr) {? ? ? ? ? ? BaseModel *model = [BaseModel initWithDictionary:dic];// 將不同子類創建出的model對象添加到我們的數組當中[_dataArray addObject:model];? ? ? ? }? ? }return_dataArray;}
這樣數組dataArray中存的就是我們想要的三種不同的對象。再去展示到頁面上就可以了。
當然在展示到Cell上的時候,不同的Model對象需要的Cell也是不同的,所以Cell的創建也是可以通過工廠模工進行創建的。
下面找個問題從去年來深圳,大概面試被問到了兩三次,個人覺得是一道比較好的面試題,實用性比較強,大概的意思是,iOS中你是怎么收集錯誤日志,用戶行為統計和分析是怎么做的?
如果找個問題你一點都答不上來,那你可能真的是一個假iOS開發工程師,或者說沒做過一個真正意義上的APP,那么我建議你還是找個正規點的公司去做開發,小公司野路子太多了,容易井底之蛙!
首先一點,你可以回答,我們項目中集成了友盟統計(或者其他第三方統計SDK),友盟統計比較強大,用戶量的增長,增長率,用戶對頁面的操作行為都有詳細的分析,也有錯誤日志列表,可以清晰的看到哪里有bug,哪里閃退。
當你回答到這里,雖然不一定能保證你能加分,但起碼不會減分了。去年去福田面試,面試官問我還有什么其他方式可以看到錯誤日志,我一時沒想起來,我說只能想到這么多,后來他跟我是這么解釋的,xcode內部是可以生成一個錯誤日志包的,也是可以分析的。大概的意思是用Xcode自帶的 symbolicatecrash 工具來解析的.crash文件,然后找到app包所對應的.dSYM文件。然后用終端命令找到出現錯誤的地方。
其實友盟統計有時候錯誤列表中有些錯誤是分析不出來具體哪個類哪行代碼出現了問題,那么久需要找到xcode中的.dSYM文件來分析了。個人如果找個點你答上來,那么你一定會另面試官刮目相看的。
但是樹欲靜而風不止,但是后來有面試官問,你自己有沒有在項目中做過用戶行為分析與統計,自己做過而不是用第三方,因為由于各種原因,這些有時候并不能滿足我們的需求,比如我還想知道用戶在什么網絡狀態下崩潰,什么位置崩潰,什么時間崩潰,崩潰前都請求了哪些接口(這個需要跟后臺接口請求日志聯合分析),而且有時候我們還想知道除了崩潰之外的錯誤信息。
這個問題就有點淡淡的憂傷,本來小編本來想把網上找的方法粘貼上來,想想還是算了,各位感興趣可以自己上網百度下,因為自己沒做過的東西,光瀏覽幾遍就想假裝做過,簡直是天方夜譚,如果你假裝知道跟面試官在那里接話,問著問著你就發現自己沒話了,你忽然間發現,自己挖的坑自己填不了,那個時候你能只能狂笑一聲,既生瑜何生亮!
當你遇到這種問題,你應該這么回答,我之前呆的都是那種中小型公司,由于進度要求,都是用的一些成熟的第三方SDK,自己還沒接觸過,不過我相信工期允許,配合服務端,還是可以設計出來的。
下面找個問題就是考你OC的基本功,問如何拷貝一個自定義對象?
這個問題大概被問到了兩三次,可是我發現我問身邊做iOS的朋友,基本上都沒答上來,因為確實不怎么常用,但是如今人為刀俎我為魚肉,何辭為?
首先要你要給你需要深拷貝的自定義對象遵守NSCopying,NSMutableCopying協議,
然后實現重寫copyWithZone或mutableCopyWithZone這個協議方法。
只需要這兩步,但是很多人這個問題都回答不上來,如果你回答上來了,恭喜你希望大大的!
請說說你項目中是怎么做的適配?
首先你至少得說出系統適配和屏幕適配,這是最基本的。
其實還有一種是字體適配,這個現在有些項目中測試或者UI會要求我們做,那么問題就來了,怎么做字體適配呢,面試官會問到這個問題的,小編在華為面試的時候被問到過?
字體適配,現在iPhone手機的機型也就5s,6,6p這三種屏幕機型,而現在UI設計師做的效果圖基本上都是按照6上面的尺寸來的,然后讓我們自己去適配, 小編百度了下,字體適配大概是這么回事,5s和6是一套尺寸,plus系列機型的px是前面兩者的1.5倍,也就是說不管是控件的控件的寬高,還是控件間的距離,還是字體的大小都按照1.5倍去適配。但是還要一種說法是,按照以iPhone6的屏幕寬度為基準,然后獲取當前屏幕的寬度除以這個尺寸,作為一個全局系數的宏,所有的約束和字體大小都乘以這個系數就可以完成字體適配。
上次小編去華為面試,面試官也比較贊同我這種說法,希望能幫到你。
界面布局你是用的什么?
這個問題,得看你擅長用什么,如果你擅長用純代碼你就說說純代碼好,如果你擅長用xib或者masonry你就說加約束更方便,反正就是一個中藥好西醫快的問題,能夠自圓其說就可以了。
小編因為平時些項目xib和masonry用得多一些,我是這么回答面試官的。
面試官,您好,我覺得這個問題,得看公司的需求,如果是中小型公司,趕進度要去拿投資,那么我會選擇用xib和sb去做界面布局,因為領導給的時間是很緊的,一切以公司業務為主,性能的問題留到后期運營階段再調整或是重構,如果是大公司或者項目不趕,那么我會選擇用純代碼,因為純代碼性能更好,但是我平時用xib和masonry更多一些。
小編的回答,一般的面試官還是比較認可的,因為現實中做項目也確實如此。
關于第三方框架的應用
一般面試官會問,你用過哪些第三方?
我相信你一定會回答,AFN,MJ,SDwebImage,這些人人都可以說出來的專業名詞,但是但凡問這個問題的面試官都會問到它們底層的原理,而SDWebImage的底層原理幾乎是面試官必問的一個問題,相信看文章的你一定深有體會,那么我們就要問了為什么這個SDwebImage的原理這么喜歡問。
我的個人理解是,因為SDWebImage實現原理涉及到了,數據的緩存機制,還有多線程的應用,特別是跟tableView的重用結合的時候,考點頗多,給面試官裝13的機會也是比較多的。
原理我找了一張圖,小編覺得這張圖還是方便理解和記憶,不過小編認為最好把這么多信息用三句話去總結出來,傳遞給面試官,這樣簡潔而且自己好記憶。
當然這個SDWebImage的原理是一個比較常見的問題,不是很難,但是當SDWebImage遇到tableViewCell圖片重用的時候,是很容易出現錯亂的,那么這個問題應該如何解決呢?
這個問題我當時去一家做游戲的大公司面試,沒回答上來,就與大公司的offer失之交臂,小編覺得這是個很好的面試題。后來我問面試官,面試官差不多是這么回答的,結合我上網查的資料,描述如下
由于cell的重用機制,在我們加載出一個cell的時候imageView數據源開啟一個下載任務并返回一個image,當cell重用時,其數據源又會開啟一個下載任務下載新的image,但關聯的對象是同一個imageView,這個時候直接setImage時會發生錯亂。
SDWebImage的處理是:
imageView對象會關聯一個下載列表(列表是給AnimationImages用的,這個時候會下載多張圖片),當tableview滑動,imageView重設數據源(url)時,會cancel掉下載列表中所有的任務,然后開啟一個新的下載任務。這樣子就保證了只有當前可見的cell對象的imageView對象關聯的下載任務能夠回調,不會發生image錯亂。
上面這段話是精髓,希望你能記住,然后把SDWebImage的代碼大致過一遍,這樣面試基本沒什么問題。
ViewController的生命周期以及執行順序
坦白講,我也搞不懂面試官為什么喜歡問這個問題,而且還要你說全,順序說對。我能怎么辦,我也很絕望啊!
當一個視圖被創建,并且在屏幕上顯示的時候
1.alloc
創建對象,分配空間
2. init;
初始化對象,初始化數據
3. loadview
從nib載入視圖
4. viewDidLoad
控制器載入完成,可以進行自定義數據,以及動態創建其他控件
5.? viewWillAppear
視圖出現在屏幕之前,馬上這個視圖就會被展現在屏幕上了
6. viewDidAppear
視圖已在屏幕上渲染完成
當一個視圖被移除屏幕并且銷毀的時候,代碼執行的順序
1. viewWillDisappear
視圖將被從屏幕上移除之前執行
2. viewDidDisappear
視圖已經被從屏幕上移除,用戶看不見這個視圖了
3. dealloc
視圖被銷毀,釋放在init和viewDidLoad中創建的對象
這個順序還是強行記住吧,沒什么好說的。
點擊button沒有反應,會有哪些原因造成的?
這個面試題據我統計,至少被問到了三四次,雖然比較好回答,但是把所有的可能性說全,還是需要整理下。
1,檢查自身試圖和父視圖的userInterfaractionEnabled是否打開
2,看button的位置是不是在父視圖上,如果沒有就當然不能點擊了
3,看button有沒有被覆蓋 最好加一個顏色確認
4,檢查button的frame
5.在父視圖上加上一個touchBegin方法,檢查一下。
6.沒有添加點擊事件
這6點是比較容易答上來的,不過小編前段時間碰到一個問題用以上6個方法都檢驗不出來,淡淡的憂傷,后來發現不知道是誰,在項目中中寫了UIButton分類,然后用runtime把系統的方法給攔截,button的點擊方法就執行不了,我想說這個大神,也是厲害。
如果用分類把系統的方法個重寫了,或者用runtime把系統的方法攔截,也會沒反應,個人覺得面試官不一定能想到這兩點,如何你跟他講出這兩點,然后延著這兩點,吹吹runtime的一些東西,還是很加分!
block的那些事?
block這個東西內容太多了,但是常用的無非就是做一些傳值,回調用途,但是面試往往往基礎部分問。
最近小編去一個比較大的公司去面試,問block什么時候在棧,什么時候在堆?問得我頭發麻
小編找了下,下面找個總結比較好記一點,但是不知道對不對,如果不對請多多指教。
以下四種情況都是在堆里,其他的都在棧里
①調用Block的copy實例方法時
②Block作為函數返回值返回時
③將Block賦值給附有__strong修飾符id類型的類或者Block類型成員變量時
④在方法名中含有usingBlock的Cocoa框架方法或Grand Central Dispatch 的API中傳遞Block時
還有有個問題去大公司也容易被問到,block的三種類型
根據isa指針,block一共有3種類型的block
_NSConcreteGlobalBlock 全局靜態
_NSConcreteStackBlock 保存在棧中,出函數作用域就銷毀
_NSConcreteMallocBlock 保存在堆中,retainCount == 0銷毀
而ARC和MRC中,還略有不同
個人覺得如果去大公司面試,block一定要深入了解,不然去了也是白去,面試面到你懷疑人生!
iOS 繪制如何1像素線條?
這個實際上xib,sb拉出來的空間,寬度設置.5,實際上不止一個像素,那么這個問題怎么解決呢
參考這個鏈接吧,http://blog.csdn.net/keleyundou/article/details/47724361
iOS的性能優化是怎么做的?并且和界面卡端問題結合起來問
面試的公司十之八九都會問這個問題,因為app的性能會直接影響用戶體驗,一般面試官都會問到。
1.最常用的就是cell的重用, 注冊重用標識符
如果不重用cell時,每當一個cell顯示到屏幕上時,就會重新創建一個新的cell
如果有很多數據的時候,就會堆積很多cell。如果重用cell,為cell創建一個ID
每當需要顯示cell 的時候,都會先去緩沖池中尋找可循環利用的cell,如果沒有再重新創建cell
2.避免cell的重新布局
cell的布局填充等操作 比較耗時,一般創建時就布局好
如可以將cell單獨放到一個自定義類,初始化時就布局好
3.提前計算并緩存cell的屬性及內容
當我們創建cell的數據源方法時,編譯器并不是先創建cell 再定cell的高度
而是先根據內容一次確定每一個cell的高度,高度確定后,再創建要顯示的cell,滾動時,每當cell進入憑虛都會計算高度,提前估算高度告訴編譯器,編譯器知道高度后,緊接著就會創建cell,這時再調用高度的具體計算方法,這樣可以方式浪費時間去計算顯示以外的cell
4.減少cell中控件的數量
盡量使cell得布局大致相同,不同風格的cell可以使用不用的重用標識符,初始化時添加控件,
不適用的可以先隱藏
5.不要使用ClearColor,無背景色,透明度也不要設置為0
渲染耗時比較長
6.使用局部更新
如果只是更新某組的話,使用reloadSection進行局部更新
7.加載網絡數據,下載圖片,使用異步加載,并緩存
8.少使用addView 給cell動態添加view
9.按需加載cell,cell滾動很快時,只加載范圍內的cell
10.不要實現無用的代理方法,tableView只遵守兩個協議
11.緩存行高:estimatedHeightForRow不能和HeightForRow里面的layoutIfNeed同時存在,這兩者同時存在才會出現“竄動”的bug。所以我的建議是:只要是固定行高就寫預估行高來減少行高調用次數提升性能。如果是動態行高就不要寫預估方法了,用一個行高的緩存字典來減少代碼的調用次數即可
性能優化和界面卡端是個非常大的話題,網上有很多文章博客講解,但是個人認為,選幾個自己容易記的記一下就可以了,那些不好記的就不用記了,如果自己平時沒做過這方面的優化,那么你下個項目就要嘗試就要去做了,不然靠看下文章,臨時背一下,面試很容易問懵逼!
沙盒的目錄結構?
這個問題也是面試比較喜歡,小編去華為面試這個問題也被問到,但是回答得不全。解答如下
/AppName.app 應用程序的程序包目錄。由于應用程序必須經過簽名,所以不能在運行時對這個目錄中的內容進行修改,否則會導致應用程序無法啟動。
/Documents/ 保存應用程序的重要數據文件和用戶數據文件等。iTunes 同步時會備份該目錄。
/Library/Caches 保存應用程序使用時產生的支持文件和緩存文件,還有日志文件最好也放在這個目錄。iTunes 同步時不會備份該目錄。
/Library/Preferences 保存應用程序的偏好設置文件(使用 NSUserDefaults 類設置時創建,不應該手動創建)。
/tmp/ 保存應用運行時所需要的臨時數據,iphone 重啟時,會清除該目錄下所有文件。
一般請求的數據放在沙盒的哪個目錄下?
還是直接上代碼吧
//存數據
NSString * sandBoxpath = [NSHomeDirectory()stringByAppendingPathComponent:@"/Documents/save"];
NSString * stroeSting? =@"yi";
[stroeStingwriteToFile:sandBoxpathatomically:YESencoding:NSUTF8StringEncodingerror:nil];
//取數據
NSString * checkString = [[NSStringalloc]initWithContentsOfFile:[NSHomeDirectory()stringByAppendingPathComponent:@"/Documents/save"]encoding:NSUTF8StringEncodingerror:nil];
NSLog(@"取出的數據是:%@",checkString);
應該很直觀了吧,小編認為把這兩個問題掌握好,沙盒這部分基本就OK了,可以放心復習其他的問題了。
面試的時候當你面完發現這家面得不怎么好,沒什么希望,當面試官文你還有什么問題要問的時候,這個時候你就要機智點,你說能不能解答下剛才那個問題的答案是什么,這方面我想回去再了解下,這個面試官還是比較樂意告訴你答案的,畢竟誰都愿意以一種居高臨下的姿態去給別人講解東西。然后你回去就好好總結,技術面試這個東西其實口才部分占的權重不是很大,只要你好好總結,面它個幾十家,我就不信你找不到工作。
目前小編只能想到這些問題,如果后面想到其他的面試好問題,會更新到這篇文章的,希望能幫到廣大iOS求職朋友。
雖然現在iOS找工作競爭比較大,不像15年之前那么輕而易舉了,但是選擇即要負責,只要還在這個行業一日,就有必要更好的完善自己的知識體系,互聯網這個行業每一年都有新東西,每一年都有火的方向,如果一味的貪多,吃在碗里,看在鍋里,恐怕還得不償失,一位面試官曾經對我這么說:你的經驗雖然比較有廣度,但是缺乏深度,回去還得修煉。
這話很有道理,不能看智能家居火了就跑著去學智能家居,看著java又火起來,又去學java,這樣每一樣你雖然都淺嘗輒止,每一樣你都不精通,都稱不上大家。
個人覺得還是先把一門語言學好,基礎打好,學扎實了,然后再去學習其他的預言,要有一門很深入的語言在心中,才能立于不敗之地。
至于面試,小編認為問到swift的公司很少,swift這門語言出來也有兩年多時間了,但是一直都是雷聲大雨點小,小編認為還是好好復習下OC的知識,出去面試才有勝算。
然后投簡歷的網站,我都是投的boss直聘,拉鉤,智聯,51job,還有中國人才熱線,現在目前這個就業形勢我覺得你還是海投比較好,集中面試比較好。
上面雖然寫了一些面試經驗,小編覺得每個人的面試情況不同,每個人的知識體系不一樣,可能體會不一樣,但是面試完了之后,一定要多多總結,這個原則是不管是對誰,都哪個行業都是適用的。
如果你手上有很多個offer,那么我建議選個規模比較大點的公司,研發部門人數多點公司,因為現在那種初創互聯網公司,特別是人數比較少的,還要靠融資苦苦支撐的公司,很容易就崩盤了,而且小公司很多東西不是很規范,如果你工作經驗很豐富,還是嘗試下大點公司啊,大公司東西規范點,而且跟著一個好的技術經理,好的CTO,能學到一些管理方式的東西,說話方面的東西。并且接觸的人脈資源也更多優秀,以后的道路更寬一些。
最后,祝各位同位同行,在這個寒冬期找找到自己的定位,走向人生巔峰,迎接白富美!