1. 程式人生 > >如何介紹你的專案

如何介紹你的專案

專案問題

APP 專案
一般面試官在面試過程中,讓求職者講一下之前的專案,好多學生只是僅僅把自己會的這些知識點說了出來,而遇到不會的了有學生就直接回答“那個模組不是我做”,但凡回這一句話的面試都沒戲。
如果按照層次劃分,APP專案可分為三層:表現層(UI介面)、資料層(網路請求資料)、業務邏輯層。如何按照模組劃分,APP專案可分為多個模組,iOS專案可以看看tabbar欄中的個數,是否還有側滑,加起來即為模組數。
無論一個專案是個人開發還是團隊開發,是上線還是沒上線,APP整個專案的業務邏輯、自己負責的模組的詳細業務邏輯、專案關鍵技術點、開發專案中遇到的問題,是無論如何都不會忘記的。

那麼,專案應注意哪一些問題:
1)APP整個專案的業務邏輯、自己負責的模組的業務邏輯。無論專案是自己做的、還是團隊開發、還是他人專案,一定搞清楚整個專案的業務邏輯,操作一下APP,搞清楚APP的業務流程,尤其注意模組間是否有資料傳遞,建議畫圖分析。
2)專案關鍵點。如果是專案是獨立開發,那麼所有的技術點都要弄明白;哪怕專案是團隊開發,核心技術點也必須要掌握。比如說,選取的APP專案是電商類的,肯定要問支付;APP是社交類的,必問即時通訊;APP是資訊展示類(新聞),必問資料處理。
3)專案遇到的問題及解決方案。在尋找專案遇到的問題,一定要找一個層次高的問題,不要舉例專案中的小問題。可以舉例一下,當時接入支付遇到問題,做加密的時候和安卓加出來不一致,網路請求不正確等。
4)適配。這裡所說的適配並不是簡簡單單的是螢幕適配、還有版本適配iOS不同版本之間是否做過特殊處理。
5)專案版本迭代。專案版本更新,每一次更新做了哪些工作,是否新添加了功能,還是改了哪些bug。

介紹APP專案的方法
介紹專案是有一定套路的,不是說的點開APP想介紹哪兒就介紹哪兒。要有一定的邏輯性,要用一些專業術語來介紹專案。
在介紹專案的時候,可以從專案整體到模組,模組從左到右,介面從上到下的順序一一介紹。或者從專案整體到模組,在介紹模組時,從重要、核心模組開始。在介紹專案時,要將專案整體定位、功能模組、主要技術都要介紹清楚,有一定的層次性。
以美團APP為例:
美團是一款及團購、旅遊、美食、酒店、外賣、電影、生活服務集一體的綜合性電商型別APP。它主要分為首頁、商家、我的、更多四個模組。首頁模組顯示了一些當前熱度較高、比較受歡迎的產品與服務;商家模組根據使用者定位的位置顯示周圍的商家資訊;我的模組中顯示一些個人訂單、錢包、積分等資訊;更多模組中包含了APP使用者偏好設定、以及常見問題處理。
此款APP是團隊開發,迭代了2個版本。當時我開發了首頁模組。首頁模組以顯示當前熱度較高、比較受歡迎的產品與服務為主。在首頁的最上面的導航欄中,包含了城市定位、搜尋框、二維碼掃描、推送訊息記錄(自己擅長的地方的技術要講出來);緊接著下面是一個scrollview,裡面有各類服務的選項,點選後可以進入相應的頁面;再下面是……;最後面是……

1、OSX 版本、Xcode版本與iOS 版本【難度係數★】
Xcode自從5.0版本之後,支援arm64
2013年9月
Xcode 5.0 iOS7
2013年3月
Xcode 5.1
2014年9月
Xcode 6.0
iOS8
2014年10月 Xcode 6.1
2015年3月 Xcode 6.2
2015年4月 Xcode 6.3
2015年7月 Xcode 6.4
2015年9月 Xcode 7
iOS9
2015年10月 Xcode 7.1
2015年12月 Xcode 7.2
2016年3月 Xcode 7.3

2、MVC設計模式是什麼? 你還熟悉什麼設計模式?【難度係數★】
設計模式:並不是一種新技術,而是一種編碼經驗,使用比如java中的介面,iphone中的協議,繼承關係等基本手段,用比較成熟的邏輯去處理某一種型別的事情,總結為所謂設計模式。面向物件程式設計中,java已經歸納了23種設計模式。
mvc設計模式 :模型,檢視,控制器,可以將整個應用程式在思想上分成三大塊,對應是的資料的儲存或處理,前臺的顯示,業務邏輯的控制。 Iphone本身的設計思想就是遵循mvc設計模式。其不屬於23種設計模式範疇。
代理模式:代理模式給某一個物件提供一個代理物件,並由代理物件控制對源物件的引用.比如一個工廠生產了產品,並不想直接賣給使用者,而是搞了很多代理商,使用者可以直接找代理商買東西,代理商從工廠進貨.常見的如QQ的自動回覆就屬於代理攔截,代理模式在iphone中得到廣泛應用.
單例模式:說白了就是一個類不通過alloc方式建立物件,而是用一個靜態方法返回這個類的物件。系統只需要擁有一個的全域性物件,這樣有利於我們協調系統整體的行為,比如想獲得[UIApplication sharedApplication];任何地方呼叫都可以得到 UIApplication的物件,這個物件是全域性唯一的。
觀察者模式: 當一個物體發生變化時,會通知所有觀察這個物體的觀察者讓其做出反應。實現起來無非就是把所有觀察者的物件給這個物體,當這個物體的發生改變,就會呼叫遍歷所有觀察者的物件呼叫觀察者的方法從而達到通知觀察者的目的。
工廠模式:
public class Factory{
public static Sample creator(int which){
if (which==1)
return new SampleA();
else if (which==2)
return new SampleB();
}
}

3、Quatrz 2D的繪圖功能的三個核心概念是什麼並簡述其作用。【難度係數★★】
上下文:主要用於描述圖形寫入哪裡;
路徑:是在圖層上繪製的內容;
狀態:用於儲存配置變換的值、填充和輪廓, alpha 值等

4、如何除錯BAD_ACCESS錯誤【難度係數★★】
1. 重寫object的respondsToSelector方法,現實出現EXEC_BAD_ACCESS前訪問的最後一個object
2. 通過 Zombie

  1. 設定全域性斷點快速定位問題程式碼所在行
  2. Xcode 7 已經集成了BAD_ACCESS捕獲功能:Address Sanitizer。 用法如下:在配置中勾選?Enable Address Sanitizer

5、lldb(gdb)常用的除錯命令?【難度係數★★】
breakpoint 設定斷點定位到某一個函式
n 斷點指標下一步
po列印物件

6、開發者證書【難度係數★★】
證書分兩種:開發者證書、釋出者證書。前者開發時使用,後者釋出使用
(1) 模擬器除錯無需程式碼簽名;真機除錯需開發者證書程式碼簽名;釋出時需釋出證書籤名
(2) 程式碼簽名需要:證書+私鑰,
(3) 真機除錯時要求在裝置上安裝描述檔案(provision profile),該檔案包含資訊:除錯者證書,
授權除錯裝置清單,應用ID。一個應用對應一個描述檔案

7、app效能測試方式【難度係數★★★】
通過Xcode提供的工具如Instrument,測試CPU,Mermory效能。也可以適用一些開源的自動化測試工具:如Frank,KIF等。

8、如何應對APP版本升級,資料結構隨之變化? 【難度係數★★★】
自己解除的Sqlite相對多一些,通常的作法是重新命名舊版資料庫檔案->建立新版本表格->匯入舊版本資料->刪除舊版本表
跨版本升級的問題,資料庫更新的相關操作不做合併,依次迭代更新
Core data接觸不多,大部分改動都在輕量化遷移支援範圍內,複雜的需要重寫指定對映關係

9、如何進行記憶體洩露檢測【難度係數★★★】
(1)Run Static Analyzer
(2)instruments
(3)在init和dealloc中列印看一下init和dealloc都會成對出現,block中呼叫self的屬性和成員變數要加__weak 或 __block

10、有方法檢視當前系統記憶體使用情況嗎? 【難度係數★★★】
1.靜態分析
通過靜態分析我們可以最初步的瞭解到程式碼的一些不規範的地方或者是存在的記憶體洩漏,這是我們第一步對記憶體洩漏的檢測。當然有一些警告並不是我們關心的可以略過。
2.通過instruments來檢查記憶體洩漏
這個方法能粗略的定位我們在哪裡發生了記憶體洩漏。方法是完成一個迴圈操作,如果記憶體增長為0就證明我們程式在該次迴圈操作中不存在記憶體洩漏,如果記憶體增長不為0那證明有可能存在記憶體洩漏,當然具體問題需要具體分析。
3.程式碼測試記憶體洩漏
在做這項工作之前我們要注意一下,在dealloc的方法中我們是否已經釋放了該物件所擁有的所有物件。觀察物件的生成和銷燬是否配對。準確的說就是init(建立物件的方法)和dealloc是否會被成對觸發(簡單說來就是走一次建立物件就有走一次dealloc該物件)。
下面是自己遇到的一些比較隱祕的造成記憶體洩漏的情況:
1.兩個物件互相擁有:也就是說物件a裡面retain/addSubview了b物件,b物件同時也retain/addSubView了a物件。注意:delegate不要用retain屬性,要用assign屬性也會導致互相擁有。
2.有時候需要用removeFromSuperView來釋放:具體說明,也許我的a物件擁有一個b物件,b物件add到了c物件上,而在我們的設計中b物件的生命週期應該和a物件相同;這時候只一句[b release]/self.b = nil是不能把b物件釋放掉的(一般情況下release會使其retainCount-1,[super dealloc]會再次將所有subView的retainCount-1,而b並不是a的subView,所有最後的一次-1沒有了);所以我們需要在之前加上[b removeFromSuperView]。

11、如何追蹤app崩潰率,如何解決線上閃退【難度係數★★★★★】

當iOS裝置上的App應用閃退時,作業系統會生成一個crash日誌,儲存在裝置上。crash日誌上有很多有用的資訊,比如每個正在執行執行緒的完整堆疊跟蹤資訊和記憶體映像,這樣就能夠通過解析這些資訊進而定位crash發生時的程式碼邏輯,從而找到App閃退的原因。通常來說,crash產生來源於兩種問題:違反iOS系統規則導致的crash和App程式碼邏輯BUG導致的crash,下面分別對他們進行分析。

違反iOS系統規則產生crash的三種類型:

(1) 記憶體報警閃退

當iOS檢測到記憶體過低時,它的VM系統會發出低記憶體警告通知,嘗試回收一些記憶體;如果情況沒有得到足夠的改善,iOS會終止後臺應用以回收更多記憶體;最後,如果記憶體還是不足,那麼正在執行的應用可能會被終止掉。在Debug模式下,可以主動將客戶端執行的動作邏輯寫入一個log檔案中,這樣程式童鞋可以將記憶體預警的邏輯寫入該log檔案,當發生如下截圖中的記憶體報警時,就是提醒當前客戶端效能記憶體吃緊,可以通過Instruments工具中的Allocations 和 Leaks模組庫來發現記憶體分配問題和記憶體洩漏問題。

(2) 響應超時
當應用程式對一些特定的事件(比如啟動、掛起、恢復、結束)響應不及時,蘋果的Watchdog機制會把應用程式幹掉,並生成一份相應的crash日誌。這些事件與下列UIApplicationDelegate方法相對應,當遇到Watchdog日誌時,可以檢查上圖中的幾個方法是否有比較重的阻塞UI的動作。

(3) 使用者強制退出
一看到“使用者強制退出”,首先可能想到的雙擊Home鍵,然後關閉應用程式。不過這種場景一般是不會產生crash日誌的,因為雙擊Home鍵後,所有的應用程式都處於後臺狀態,而iOS隨時都有可能關閉後臺程序,當應用阻塞介面並停止響應時這種場景才會產生crash日誌。這裡指的“使用者強制退出”場景,是稍微比較複雜點的操作:先按住電源鍵,直到出現“滑動關機”的介面時,再按住Home鍵,這時候當前應用程式會被終止掉,並且產生一份相應事件的crash日誌。

常見的崩潰原因基本都是程式碼邏輯問題或資源問題,比如陣列越界,訪問野指標或者資源不存在,或資源大小寫錯誤等。

13、APP釋出的上架流程【難度係數★★★★】
1.登入應用釋出網站新增應用資訊;
2.下載安裝釋出證書;
3.選擇釋出證書,使用Archive編譯釋出包,用Xcode將程式碼(釋出包)上傳到伺服器;
4.等待稽核通過;
5.生成IPA:選單欄->Product->Archive.

14、對沙盒的理解【難度係數★★★】
每個iOS應用都被限制在“沙盒”中,沙盒相當於一個加了僅主人可見許可權的資料夾,及時在應用程式安裝過程中,系統為每個單獨的應用程式生成它的主目錄和一些關鍵的子目錄。蘋果對沙盒有幾條限制:
1.應用程式在自己的沙盒中運作,但是不能訪問任何其他應用程式的沙盒;
2.應用之間不能共享資料,沙盒裡的檔案不能被複制到其他應用程式的資料夾中,也不能把其他應用資料夾複製到沙盒中;
3.蘋果禁止任何讀寫沙盒以外的檔案,禁止應用程式將內容寫到沙盒以外的資料夾中;
4.沙盒目錄裡有三個資料夾:Documents——儲存;應用程式的資料檔案,儲存使用者資料或其他定期備份的資訊;Library下有兩個資料夾,Caches儲存應用程式再次啟動所需的資訊,Preferences包含應用程式的偏好設定檔案,不可在這更改偏好設定;temp存放臨時檔案即應用程式再次啟動不需要的檔案。
獲取沙盒根目錄的方法,有幾種方法:用NSHomeDirectory獲取。
獲取Document路徑:NSSearchPathForDirectoriesInDomains (NSDocumentDirectory,NSUserDomainMask,YES).

15、對瀑布流的理解【難度係數★★★★】
首先圖片的寬度都是一樣的,1.將圖片等比例壓縮,讓圖片不變形;2.計算圖片最低應該擺放的位置,哪一列低就放在哪;3.進行最優排列,在ScrollView的基礎上新增兩個tableView,然後將之前所計算的scrollView的高度通過tableView展示出來。
如何使用兩個TableView產生聯動:將兩個tableView的滾動事件禁止掉,最外層scrollView滾動時將兩個TableView跟著滾動,並且更改contentOffset,這樣產生效果滾動的兩個tableView。
16、記憶體的使用和優化的注意事項【難度係數★★★】
1)重用問題:如UITableViewCells、UICollectionViewCells、UITableViewHeaderFooterViews設定正確的reuseIdentifier,充分重用;
2)儘量把views設定為不透明:當opque為NO的時候,圖層的半透明取決於圖片和其本身合成的圖層為結果,可提高效能;
3)不要使用太複雜的XIB/Storyboard:載入時就會將XIB/storyboard需要的所有資源,包括圖片全部載入記憶體,即使未來很久才會使用。那些相比純程式碼寫的延遲載入,效能及記憶體就差了很多;
4)選擇正確的資料結構:學會選擇對業務場景最合適的陣列結構是寫出高效程式碼的基礎。比如,陣列: 有序的一組值。使用索引來查詢很快,使用值查詢很慢,插入/刪除很慢。字典: 儲存鍵值對,用鍵來查詢比較快。集合: 無序的一組值,用值來查詢很快,插入/刪除很快。
5)gzip/zip壓縮:當從服務端下載相關附件時,可以通過gzip/zip壓縮後再下載,使得記憶體更小,下載速度也更快。
6)延遲載入:對於不應該使用的資料,使用延遲載入方式。對於不需要馬上顯示的檢視,使用延遲載入方式。比如,網路請求失敗時顯示的提示介面,可能一直都不會使用到,因此應該使用延遲載入。
7)資料快取:對於cell的行高要快取起來,使得reload資料時,效率也極高。而對於那些網路資料,不需要每次都請求的,應該快取起來,可以寫入資料庫,也可以通過plist檔案儲存。
8)處理記憶體警告:一般在基類統一處理記憶體警告,將相關不用資源立即釋放掉
9)重用大開銷物件:一些objects的初始化很慢,比如NSDateFormatter和NSCalendar,但又不可避免地需要使用它們。通常是作為屬性儲存起來,防止反覆建立。
10)避免反覆處理資料:許多應用需要從伺服器載入功能所需的常為JSON或者XML格式的資料。在伺服器端和客戶端使用相同的資料結構很重要;
使用Autorelease Pool:在某些迴圈建立臨時變數處理資料時,自動釋放池以保證能及時釋放記憶體;
11)正確選擇圖片載入方式:詳情閱讀細讀UIImage載入方式

17、plist檔案是用來做什麼的。一般用它來處理一些什麼方面的問題。【難度係數★★★】
plist是iOS系統中特有的檔案格式。我們常用的NSUserDefaults偏好設定實質上就是plist檔案操作。plist檔案是用來持久化儲存資料的。

我們通常使用它來儲存偏好設定,以及那些少量的、陣列結構比較複雜的不適合儲存資料庫的資料。比如,我們要儲存全國城市名稱和id,那麼我們要優先選擇plist直接持久化儲存,因為更簡單。

18、在提交蘋果稽核時,遇到哪些問題被拒絕【難度係數★★★】
1)最常見到的就是app中有虛擬物品交易,但是不是走內購導致被拒。
2)音訊類App或者使用到音訊相關的app,因為版權問題而被拒
3)App出現必閃退而被拒
4)人工刷廣告瀏覽量或者廣告點選率的應用程式將會被拒絕。
5)包含空iAd廣告的應用程式將會被拒絕。
6)通過蜂窩網路傳輸的音訊流內容每5分鐘不得超過5MB。
7)主要功能為報時的Watch app將會被拒。(2015.4 新增)
8)只是簡單的網頁剪下、內容整合或者收集連結的應用程式可能會被拒絕。
9) 在未經使用者事先許可,或未告知使用者如何使用資訊以及在何處使用資訊的情況下,應用程式不能傳輸使用者資料。
10)如果應用程式傳送病毒、檔案、計算機程式碼或程式,並且對APN服務的正常執行造成損害或中斷,那麼該程式將會被拒絕。

19、響應訊息【難度係數★★★】
1xx:資訊響應類,表示接收到請求並且繼續處理
2xx:處理成功響應類,表示動作被成功接收、理解和接受
3xx:重定向響應類,為了完成指定的動作,必須接受進一步處理
4xx:客戶端錯誤,客戶請求包含語法錯誤或者是不能正確執行
5xx:服務端錯誤,伺服器不能正確執行一個正確的請求;

20、熟悉CocoaPods麼?能大概講一下工作原理麼?【難度係數★★★】
它會為我們建立一個工作區間,然後將所有在cocoapods中的引入的第三方庫以libPods.a這樣的方式引入到我們的工程中,這樣就可以直接訪問第三方庫了。

21、你一般是怎麼用Instruments的?【難度係數★★★】
使用Allocations來檢測記憶體和堆疊資訊
使用Leaks檢測記憶體的使用情況,包括記憶體洩露問題
使用Zombies來檢測過早釋放的殭屍物件,通過它可以檢測出在哪裡崩潰的。
使用Time Profiler來檢測CPU記憶體使用情況

22、你一般是如何除錯Bug的?【難度係數★★★】
Bug分為測試中的Bug和線上的Bug:
線上Bug:專案使用了友盟統計,因此會有崩潰日誌,通過解析dYSM可以直接定位到大部分bug崩潰之處。解決線上bug需要從主幹拉一個新的分支,解決bug並測試通過後,再合併到主幹,然後上線。若是多團隊開發,可以將fix bug分支與其他團隊最近要上線的分支整合,然後整合測試再上線。
測試Bug:根據測試所反饋的bug描述,若語義不清晰,則直接找到提bug人,操作給開發人員看,最好是可以bug復現。解決bug時,若能根據描述直接定位bug出錯之處,則好處理;若無法直觀定位,則根據bug型別分幾種處理方式,比如崩潰的bug可以通過instruments來檢測、資料顯示錯誤的bug,則需要閱讀程式碼一步步檢視邏輯哪裡寫錯。