*面試心聲:總結起來就是把基礎的東西弄好,複雜的東西瞭解就ok了!html
*此題庫是北上廣深杭各大小公司面試題。java
*注:現在社會仍是得靠本事,看面試題只是多了一個機會,珍惜機會的同時提升本身硬實力纔是真理!ios
友情提示:題庫過長,全200道只能上傳100道,須要完整PDF文檔,可進入小編iOS交流羣:624212887,羣文件直接獲取,更多技術書籍,面試資料盡在此,歡迎入駐,交流探討c++
1.給定一個字符串,輸出本字符串中只出現一次而且最靠前的那個字符的位置?好比「abaccddeeef」則是b,輸出2
答:面試
int main() { char a[80] = "abaccddeeef\0"; char ch; int i, m, b[80]; int flag = 0; ch = getchar();//獲取一個字符 m = strlen(a); for (i = 0; i < m; ++i){ if (a[i] == ch){//找到了,直接判斷是否相等 b[flag] = i+1;//記錄位置 flag += 1; } } if (flag == 0)printf ("no"); else { printf ("%d\n", flag); for (i = 0; i < flag; i++){//對位置進行輸出,用循環 printf ("%d ", b[i]); } printf ("\n"); } return 0; }
2.實現一個冒泡排序或者快速排序
答:冒泡排序:sql
intarray[5] = { 28,27,36,45,8}; for (int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { if (array[j] > array [j + 1]){ int temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; }}} for(int i = 0; i < 5; i++) { printf("%d\n",array[i]);}
3.請編寫一個函數用於計算階乘
答:數據庫
int f(int i) {intt=1,j; for(j=1;j<=i;j++) t=t*j; return t; }
4.Cocoa Touch提供了幾種Core編程
Animation過渡類?後端
答:Cocoa Touch提供了4種Core設計模式
Animation過渡類型,分別爲:交叉淡化、推擠、顯示和覆蓋。
5.iOS平臺怎麼作數據的持久化?coredata和sqlite有無必然聯繫?coredata是一個關係型數據嗎?
答:數據的持久化本質上都是就是寫文件,但從邏輯上又分紅不少種,好比寫入沙盒,好比存到網絡上,好比寫入數據庫。
core data是對sqlite的封裝,由於sqlite是c語言的api,然而有人也須要obj-c的api,因此有了core data ,另外,core data不只僅是把c的api翻譯成oc的api,還提供了一些管理的功能,使用更加方便。
App升級以後數據庫字段或者表有更改會致使crash,CoreData的版本管理和數據遷移變得很是有用,手動寫sql語句操做仍是麻煩一些。
CoreData不光能操縱SQLite,CoreData和iCloud的結合也很好,若是有這方面需求的話優先考慮CoreData。
CoreData並非直接操縱數據庫,好比:使用CoreData時不能設置數據庫的主鍵,目前仍須要手動操做。
6.Object-c的類能夠多重繼承麼?能夠實現多個接口麼?category是什麼?重寫一個類的方式用繼承好仍是分類好?爲何?
答: Object-c的類不能夠多重繼承;能夠實現多個接口,經過實現多個接口能夠完成C++的多重繼承;Category是類別,通常狀況用分類好,用Category去重寫類的方法,僅對本Category有效,不會影響到其餘類與原有類的關係。
7.#import跟#include有什麼區別,@class呢?#import<>跟#import」」有什麼區別?
答: #import是Objective-C導入頭文件的關鍵字,#include是C/C++導入頭文件的關鍵字,使用#import頭文件會自動只導入一次,不會重複導入,至關於#include和#pragma once;@class告訴編譯器某個類的聲明,當執行時,纔去查看類的實現文件,能夠解決頭文件的相互包含;#import<>用來包含系統的頭文件,#import」」用來包含用戶頭文件。
8.屬性readwrite,readonly,assin,retain,copy,nonatomic各是什麼做用,在哪一種狀況下用?
答: readwrite是可讀可寫特性;須要生成getter方法和setter方法時
readonly是隻讀特性只會生成getter方法不會生成setter方法;不但願屬性在類外改變
assign是賦值特性,setter方法將傳入參數賦值給實例變量;僅設置變量時;
retain表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的retaincount會+1;
copy表示拷貝特性,setter方法將傳入對象複製一份;須要徹底一份新的變量時。
nonatomic非原子操做,決定編譯器生成的setter
getter是不是原子操做,atomic表示多線程安全,通常使用nonatomic
答:
-(void)setName:(NSString *) str { [str retain]; [name release]; name = str; } - (void)setName:(NSString *)str { id t = [str copy]; [name release]; name = t; }
答:編譯時是NSString的類型;運行時是NSData類型的對象
11.當前已經編程實現函數:int
rand100().該函數可返回0~99的隨機整數,且能夠保證等機率.請利用該函數實現int rand10000(),要求等機率返回0~9999的隨機數.(不可以使用其餘的系統函數)
12.湯姆如今要在家裏舉行宴會,他雖然有不少筷子,但這些筷子的長度並不徹底相同,先已知每根筷子的長度,要求每位客人都能拿到兩根長度相同的筷子,求最多可邀請的客人數.
編程實現:int getMax(int arrLength[N])
13.現有一個整數序列,你能夠交換其中的任意兩個數以獲得一個新序列.求共能獲得多少種可能結果.(注意:3,3,3,3不管怎麼交換,只能獲得一個序列)
編程實現:int getTotal(int arrOrigin[N])
14.現有一個M行N列的數組,要求安裝反向斜對角線(右上->左下)的方式,打印該數組.編程實現:intprintMatrix[int arrMatrix[M][N]]
下面樣例的打印順序爲:
0->1->4->2->5->8->3->6->9->7->10->11 123 4567 8910 11
15.在UIKit中,frame與bounds的關係是( C )
A. frame是bounds的別名
B. frame是bounds的繼承類
C. frame的參考系是父規圖座標, bounds的參考系是自身的座標
D.frame的參考系是自身座標,bounds的參考系是父規圖的座標
16.一個類的delegate(代理)的做用不正確的是( D )
A.delegate中的函數在其餘類中實現
B.主要用於不一樣類型的對象之間一對一傳遞消息
C.沒有指派則不會觸發
D.能夠一個對象的delegate指派給多個其餘類型的對象
17.下面關於Objective-C內存管理的描述錯誤的是(A )
A.當使用ARC來管理內存時,對象的retain,dealloc方法不會被調用
B.autoreleasepool在drain的時候會釋放在其中分配的對象
C.當使用ARC來管理內存時,在線程中大量分配對象而不用autoreleasepool則可能會形成內存泄露
D.在使用ARC的項目中不能使用NSZone
18.下面block定義正確的是( A )
A.tyoedef void(^SuccessBlock)(BOOLsuccess);
B. tyoedef void(^SuccessBlock)(NSStringvalue,BOOL success);
C. tyoedef void^(SuccessBlock)(NSStringvalue,BOOL success);
D. tyoedef void^(SuccessBlock)(NSString*value);
19.UIButton從子類到父類一次繼承自:( D )
A. UIView-> UIViewController->UIController
B. UIResponder-> UIControl-> UIView
C. UIControl-> UIResponder->UIViewController
D. UIControl-> UIView-> UIResponder
20.下列關於iOS開發中類方法的使用描述,錯誤的是:( C )
A.類方法能夠調用類方法
B.類方法不能夠調用實例方法,可是類方法能夠經過建立對象來訪問實例方法
C.類方法不可使用實例變量,包括self(可使用self)
D.類方法做爲消息,能夠被髮送到類或者對象裏面去
21.什麼狀況下使用關鍵字weak和assign有何不一樣?
答:assign指針賦值,不對引用計數操做,使用以後若是沒有置爲nil,可能就會產生野指針;而weak一旦不進行使用後,永遠不會使用了,就不會產生野指針!
答: Object-c的類不能夠多重繼承;能夠實現多個接口,經過實現多個接口能夠完成C++的多重繼承;Category是類別,通常狀況用分類好,用Category去重寫類的方法,僅對本Category有效,不會影響到其餘類與原有類的關係。
23.如何用iOS設備進行性能測試?
答: Profile-> Instruments ->Time Profiler
24.咱們說的oc是動態運行時語音是什麼意思?
答案:多態。主要是將數據類型的肯定由編譯時,推遲到了運行時。這個問題其實淺涉及到兩個概念,運行時和多態。簡單來講,運行時機制使咱們直到運行時纔去決定一個對象的類別,以及調用該類別對象指定方法。多態:不一樣對象以本身的方式響應相同的消息的能力叫作多態。意思就是假設生物類(life)都用有一個相同的方法-eat;那人類屬於生物,豬也屬於生物,都繼承了life後,實現各自的eat,可是調用是咱們只需調用各自的eat方法。也就是不一樣的對象以本身的方式響應了相同的消息(響應了eat這個選擇器)。所以也能夠說,運行時機制是多態的基礎。
25.你的項目何時選擇使用GCD,何時選擇NSOperation?
答:項目中使用NSOperation的優勢是NSOperation是對線程的高度抽象,在項目中使用它,會使項目的程序結構更好,子類化NSOperation的設計思路,是具備面向對象的優勢(複用、封裝),使得實現是多線程支持,而接口簡單,建議在複雜項目中使用。項目中使用GCD的優勢是GCD自己很是簡單、易用,對於不復雜的多線程操做,會節省代碼量,而Block參數的使用,會是代碼更爲易讀,建議在簡單項目中使用。
26.讀文件是輸入流仍是輸出流?
東西讀入內存就是輸入流東西從內存寫到記錄存儲輸出流而咱們自己就以記錄存儲爲原點全部會有不解的感受~java io流按照java io流的方向能夠分爲輸入流和輸出流輸入流是將資源數據讀入到緩衝Buffer中,輸出流是將緩衝Buffer中的數據按照指定格式寫出到一個指定的位置,因此這兩個流通常同時使用,纔有意義。例如你要作文件的上傳,你要先用輸入流將待上傳文件讀入緩衝,而後用輸出流將文件寫出到網絡服務器的一個位置,則上傳成功;如果文件下載,則先得到輸入流,來讀取網絡服務器中的一個文件,而後用輸出流寫到本地的一個文件中;還有例如文件的拷貝,也是先用輸入流讀再用輸出流寫出去的很好的例子,你能夠先作一個小例子試試,對你理解java io有幫助
27.簡述CALayer和UIView的關係
答:UIView和CALayer是相互依賴的關係。UIView依賴與calayer提供的內容,CALayer依賴uivew提供的容器來顯示繪製的內容。歸根到底CALayer是這一切的基礎,若是沒有CALayer,UIView自身也不會存在,UIView是一個特殊的CALayer實現,添加了響應事件的能力。
結論:
UIView來自CALayer,高於CALayer,是CALayer高層實現與封裝。UIView的全部特性來源於CALayer支持。
28.聲明一個靜態方法和一個實例方法
答:先說實例方法,當你給一個類寫一個方法,若是該方法須要訪問某個實例的成員變量時,那麼就將該方法定義成實例方法。一類的實例一般有一些成員變量,其中含有該實例的狀態信息。而該方法須要改變這些狀態。那麼該方法須要聲明成實例方法。
靜態方法正好相反,它不須要訪問某個實例的成員變量,它不須要去改變某個實例的狀態。咱們把該方法定義成靜態方法。
29.常見的Object-C的數據類型有哪些?和Cd基本數據類型有什麼區別?
答: object-c的數據類型有nsstring,nsnumber,nsarray,nsmutablearray,nsdata等等,這些都是class,建立後即是對象,而c語言的基本數據類型int,只是必定字節的內存空間,用於存放數值;而object-c的nsnumber包含有父nsobject的方法和nsnumber本身的方法,能夠完成複雜的操做。
30.UIView的動畫效果有哪些
如UIViewAnimationOptionCurveEaseInOut
UIViewAnimationOptionCurveEaseIn
UIViewAnimationOptionCurveEaseOut
UIViewAnimationOptionTransitionFlipFromLeft
UIViewAnimationOptionTransitionFlipFromRight
UIViewAnimationOptionTransitionCurlUp
UIViewAnimationOptionTransitionCurlDown
31.你瞭解svn,cvs等版本控制工具麼?
答:瞭解.
32.靜態連接庫(瞭解一下)
答:靜態庫是程序代碼的集合,是共享代碼的一種方式
靜態庫是閉源的存在形式.a和.framework
鏈接時,靜態庫會被徹底的複製到可執行文件中,被屢次使用就會有冗餘拷貝,至關於java裏的jar包,把一些類編譯到一個包中,在不一樣的工程中若是導入此文件就可使用裏面的類,
33.什麼是沙箱模型?哪些操做是屬於私有api範疇?
答:一、應用程序能夠在本身的沙盒裏運做,可是不能訪問任何其餘應用程序的沙盒。
二、應用程序間不能共享數據,沙盒裏的文件不能被複制到其餘應用程序文件夾中,也不能把其餘應用程序文件夾中的文件複製到沙盒裏。
三、蘋果禁止任何讀、寫沙盒之外的文件,禁止應用程序將內容寫到沙盒之外的文件夾中。
四、沙盒根目錄裏有三個文件夾:Documents,通常應該把應用程序的數據文件存到這個文件夾裏,用於存儲用戶數據或其餘應該按期備份的信息。Library,下有兩個文件夾,Caches存儲應用程序再次啓動所需的信息,Preferences包含應用程序偏好設置文件,不過不要在這裏修改偏好設置。temp,存放臨時文件,即應用程序再次啓動不須要的文件。
沙盒根目錄裏有三個文件夾分別是:documents,tmp,Library。
一、Documents目錄:您應該將全部de應用程序數據文件寫入到這個目錄下。這個目錄用於存儲用戶數據或其它應該按期備份的信息。
二、AppName.app目錄:這是應用程序的程序包目錄,包含應用程序的自己。因爲應用程序必須通過簽名,因此您在運行時不能對這個目錄中的內容進行修改,不然可能會使應用程序沒法啓動。
三、Library目錄:這個目錄下有兩個子目錄:Caches和Preferences
Preferences目錄:包含應用程序的偏好設置文件。您不該該直接建立偏好設置文件,而是應該使用NSUserDefaults類來取得和設置應用程序的偏好.
Caches目錄:用於存放應用程序專用的支持文件,保存應用程序再次啓動過程當中須要的信息。
四、tmp目錄:這個目錄用於存放臨時文件,保存應用程序再次啓動過程當中不須要的信息。
iOS沙盒(sandbox)中的幾個目錄獲取方式:
//獲取沙盒主目錄路徑 NSString *homeDir = NSHomeDirectory(); //獲取Documents目錄路徑 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docDir = [paths objectAtIndex:0]; //獲取Caches目錄路徑 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *cachesDir = [paths objectAtIndex:0]; //獲取tmp目錄路徑 NSString *tmpDir = NSTemporaryDirectory(); //獲取當前程序包中一個圖片資源(apple.png)路徑 NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"apple" ofType:@"png"]; UIImage *appleImage = [[UIImage alloc] initWithContentsOfFile:imagePath]; 例子: NSFileManager* fm=[NSFileManagerdefaultManager]; if(![fm fileExistsAtPath:[selfdataFilePath]]){ //下面是對該文件進行制定路徑的保存 [fm createDirectoryAtPath:[selfdataFilePath] withIntermediateDirectories:YES attributes:nil error:nil]; //取得一個目錄下得全部文件名 NSArray *files = [fm subpathsAtPath: [selfdataFilePath] ]; //讀取某個文件 NSData *data = [fm contentsAtPath:[selfdataFilePath]]; //或者 NSData *data = [NSDatadataWithContentOfPath:[self dataFilePath]]; }
34.協議是什麼?有什麼做用?
協議:聲明一系列的方法,可由任何類實施,即便遵照該協議的類沒有共同的超類。協議方法定義了獨立於任何特定類的行爲。簡單的說,協議就是定義了一個接口,其餘類負責來實現這些接口。若是你的類實現了一個協議的方法時,則說該類遵循此協議。
協議的做用:
1.定義一套公用的接口(Public)
@required:必須實現的方法
@optional:可選實現的方法(能夠所有都不實現)
2.委託代理(Delegate)傳值:
它自己是一個設計模式,它的意思是委託別人去作某事。
好比:兩個類之間的傳值,類A調用類B的方法,類B在執行過程當中遇到問題通知類A,這時候咱們須要用到代理(Delegate)。
又好比:控制器(Controller)與控制器(Controller)之間的傳值,從C1跳轉到C2,再從C2返回到C1時須要通知C1更新UI或者是作其它的事情,這時候咱們就用到了代理(Delegate)傳值。
35.你在開發大型項目時,如何進行內存泄露檢測的?
能夠經過xcode的自帶工具run---start with performance tool裏有instruments下有個leaks工具,
啓動此工具後,運行項目,工具裏能夠顯示內存泄露的狀況,雙擊可找到源碼位置,能夠幫助進行內存泄露的處理。
36.你實現過一個框架或者庫以供別人使用麼?若是有,請談一談構建框架或者庫是的經驗;若是沒有,請設想和設計框架的public的API,並指出大概須要如何作,須要注意一些什麼方面,來方便別人容易地使用你的框架.
37.app從建立應用到上架過程(appstore)
在你開始將程序提交到App Store以前,你須要有一個App ID,一個有效的發佈證書,以及一個有效的Provisioning profile。
在itunesconnect網站上,建立app應用,設置對應信息,上傳app打包文件,提交等待審覈
38.用你熟悉的語音,編程實現Fibonacci數列:int F(intn);
Fibonacci數列遞推式F(n) = F(n-1) +F(n-2) F(1) = 1 F(2) = 2 F(3) = 3 F(4) = 5 F(5) = 8 int F(int n){ if(n == 1){ return1; } return f(n-1)+f(n-2); }
39.給定兩個排好序的數組A,B,請寫一個函數,從中找出他們的公共元素:findCommon(A,B)並列舉其餘可能的查找方法,越多越好
例如:
Array A = [1, 3, 5, 6, 9] Array B = [2, 3, 6, 8, 10] 返回結果= [3, 6] void FindCommon(int* a, int* b, int n) { int i = 0; int j = 0 ; while(i < n && j < n){ if (a[i] < b[j]) ++i ; else if(a[i] == b[j]) { cout << a[i] << endl ; ++i ; ++j ; } else// a[i] > b[j] ++j ; }
40.KVO的實現原理?
答:KVO:當指定的對象的屬性被修改了,容許對象接收到通知的機制。
41.如何給一個對象的私有屬性賦值?
答:利用KVC即鍵值編碼來給對象的私有屬性賦值.
42.block的本質是什麼?爲啥在block裏面更改外面變量的值,要給外面的變量加_block修飾,加_block修飾的原理是什麼?
答: (1) block本質是一個數據類型,多用於參數傳遞,代替代理方法, (有多個參數須要傳遞或者多個代理方法須要實現仍是推薦使用代理方法),少用於當作返回值傳遞. block是一個OC對象,它的功能是保存代碼片斷,預先準備好代碼,並在須要的時候執行.
(2)由於使用block代碼塊可能會引發內部循壞引用,因此應在block定義前加上修飾
43.block在哪一種狀況下會形成循環引用,如何解決?
答:(1)從兩方面分析形成循環引用問題
當self擁有一個block的時候,在block又調用self的方法(或者self所擁有的某個屬性)。造成你中有我,我中有你,這種時候會形成循環引用
把某個實例變量變成本地臨時變量,強引用將直接指向這個本地臨時變量,但本地臨時變量通常都會很快釋放,因此通常考慮第一種狀況
(2)解決方案:對block進行修飾__weak(arc)或__block(mrc)
44.NSURLSession在什麼狀況下回存在循環引用的問題,怎麼解決?
答: (1)在使用NSURLSession簽定其代理的時候會存在循環引用問題,由於其代理是retain強引用
(2)解決方案
(1)在下載完成後取消NSURLSession會話並釋放Session,賦值爲nil。
(2)再視圖將要消失時也執行一樣的操做。爲了防止沒有下載完成就跳轉控制器。
具體以下:
/**視圖將要消失的時候,取消session*/ - (void)viewWillDisappear:(BOOL)animated { [superviewWillDisappear:animated]; //任務完成,取消NSURLSession [self.sessioninvalidateAndCancel]; //釋放會話 self.session =nil; }
45.如何本身實現GET緩存?
答:1.使用GET請求數據
2.iOS系統SDK已經作好了緩存。須要的僅僅是設置下內存緩存大小、磁盤緩存大小、以及緩存路徑,代碼以下
NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil];
[NSURLCache setSharedURLCache:urlCache];
46.在使用SQLite過程當中,若是多條線程同時操做同一數據庫會形成什麼問題,怎麼解決?
答:(1)容易形成系統崩潰
(2)解決方案:開啓第3種串行模式,使用一個類(單例方式)操做數據庫。
47.若是提交一個Json格式的數據給後臺服務器,後臺服務器返回的是一段普通文字,用NSURLConnection/NSURLSession/AFN分別如何實現?
答:1.使用NSURLConnection發送請求的步驟很簡單
(1)建立一個NSURL對象,設置請求路徑(設置請求路徑)
(2)傳入NSURL建立一個NSURLRequest對象,設置請求頭和請求體(建立請求對象)
(3)使用NSURLConnection發送NSURLRequest(發送請求)
2.使用NSURLSession發送請求的步驟很簡單
1)肯定請求路徑(通常由公司的後臺開發人員以接口文檔的方式提供),GET請求參數直接跟在URL後面
2)建立請求對象(默認包含了請求頭和請求方法【GET】),此步驟能夠省略
3)建立會話對象(NSURLSession)
4)根據會話對象建立請求任務(NSURLSessionDataTask)
5)執行Task
6)當獲得服務器返回的響應後,解析數據(XML|JSON|HTTP)
48.請描述一下SDWebImage內部實現的原理
答:SDWebImage底層實現有沙盒緩存機制,主要由三塊組成
一、內存圖片緩存
二、內存操做緩存
三、磁盤沙盒緩存
49.你對runtime都有哪些瞭解,你在實現開發過程當中,或是你在所使用的第三方框架中,有沒有使用過runtime的,若是有,請你描述一下其內部實現機制
答:Runtime:runtime是一套比較底層的純C語言API,屬於1個C語言庫,包含了不少底層的C語言API。在咱們平時編寫的OC代碼中,程序運行過程時,其實最終都是轉成了runtime的C語言代碼, runtime算是OC的幕後工做者.
50.線程間怎麼通訊?
(1)GCD:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ //下載圖片 UIImage *image = nil; dispatch_async(dispatch_get_main_queue(),^{ //回到主線程 }); (2)NSThread的線程通訊 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ //下載圖片 UIImage *image = nil; [selfperformSelector:@selector(settingImage:) onThread:[NSThread mainThread]withObject:image waitUntilDone:YES modes:nil]; }
這種狀況也適用於子線程之間的通訊。
51.網絡圖片處理問題中怎麼解決一個相同的網絡地址重複請求的問題?
答案:利用字典圖片地址爲key,下載操做爲value
52.自動釋放池底層怎麼實現?
答:自動釋放池以棧的形式實現:當你建立一個新的自動釋放池時,它將被添加到棧頂.當一個對象收到發送autorelease消息時,他被添加到當前線程的處於棧頂的自動釋放池中,當自動釋放池被回收時,他們從棧中被刪除,而且會給池子裏面全部的對象都會作一次release操做
53.不用中間變量,用兩種方法交換A和B的值
A = A+B;
B = A - B;
A = A - B;
54.簡單描述一下客戶端的緩存機制?
答案:沒法簡述,詳細瞭解下,明白了夠裝逼就好http://www.cnblogs.com/wendingding/p/3950198.html
55.控制器View的生命週期及相關函數是什麼?你在開發中是如何用的?
1.在視圖顯示以前調用viewWillAppear;該函數能夠調用屢次;
2.視圖顯示完畢,調用viewDidAppear;
3.在視圖消失以前調用viewWillDisAppear;該函數能夠調用屢次(如須要);
4.在佈局變化先後,調用viewWill/DidLayoutSubviews處理相關信息;
56.NSRunLoop的實現機制,及在多線程中如何使用?
答案:NSRunLoop是iOS的消息機制的處理模式
1NSRunloop的主要做用:控制runloop裏面線程的執行和休眠,在有事情作的時候使擋牆NSRunloop控制的線程工做,沒有事情作讓當前runloop的控制線程休眠.
2.runloop就是一直在循環檢測,從線程start到線程end,檢測inputsourse(如點擊,雙擊等操做)異步時間,檢測timesourse同步事件,見到檢測到輸入源會執行處理函數,首先會產生通知,corefunction向線程添加runloop observers來監聽事件,意在監聽事件發生時來作處理。
3.runloopmode是一個集合,包括監聽:事件源,定時器,以及需通知的runloop observers
1.只有在爲你的程序建立次線程的時候,才須要運行run loop。對於程序的主線程而言,run loop是關鍵部分。Cocoa提供了運行主線程run loop的代碼同時也會自動運行run loop。IOS程序UIApplication中的run方法在程序正常啓動的時候就會啓動run loop。若是你使用xcode提供的模板建立的程序,那你永遠不須要本身去啓動run loop
2.在多線程中,你須要判斷是否須要run loop。若是須要run loop,那麼你要負責配置run loop並啓動。你不須要在任何狀況下都去啓動run loop。好比,你使用線程去處理一個預先定義好的耗時極長的任務時,你就能夠毋需啓動run loop。Run loop只在你要和線程有交互時才須要
57.簡單說一下APP的啓動過程,從main文件開始提及
進入main函數,在main.m的main函數中執行了UIApplicationMain這個方法,這是ios程序的入口點!
int UIApplicationMain(int argc, char argv[], NSString principalClassName, NSString *delegateClassName)
argc、argv:ISO C標準main函數的參數,直接傳遞給UIApplicationMain進行相關處理便可
principalClassName:指定應用程序類,該類必須是UIApplication(或子類)。若是爲nil,則用UIApplication類做爲默認值
delegateClassName:指定應用程序類的代理類,該類必須遵照UIApplicationDelegate協議
此函數會根據principalClassName建立UIApplication對象,根據delegateClassName建立一個delegate對象,並將該delegate對象賦值給UIApplication對象中的delegate屬性
lUIApplication對象會依次給delegate對象發送不一樣的消息,接着會創建應用程序的main runloop(事件循環),進行事件的處理(首先會調用delegate對象的application:didFinishLaunchingWithOptions:)
程序正常退出時這個函數才返回。若是進程要被系統強制殺死,通常這個函數還沒來得及返回進程就終止了
58.第三方API你是怎麼用的?
cocoa pod導入
59.用預處理指令#define聲明一個常數,用以代表一年中有多少秒?(忽略閏年問題)
答:#define second 3652460*60
60.UITableView須要實現哪些代理?列出UITableView代理中必須實現的與其餘一些經常使用的函數.
答:
-( NSInteger )tableView:( UITableView *)tableViewnumberOfRowsInSection:( NSInteger)section;
一組有多少行
-( UITableViewCell *)tableView:( UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath;
每行中的cell的實現以上兩個方法爲必需要實現的
經常使用的有
選中之後事件設置
-( CGFloat )tableView:( UITableView )tableViewheightForRowAtIndexPath:( NSIndexPath)indexPath
設置cell的高度
等等。。。。。
61.在iOS上開發一個應用程序時怎麼作的?
答:首先,要有一個MAC系統(買一臺蘋果電腦,蘋果本或者MACmini),沒有這個條件能夠裝一個黑蘋果的mac系統或者裝一個虛擬機。而後裝一個X-CODE開發環境。要是學習ios開發的話,這些就能夠了。若是要開發、上線的話,就得準備iphone/ipod、ipad作爲測試機,到蘋果申請一個開發者帳號,每一年的年費99美圓。再而後接着就能夠開發你的程序了,開發完畢以後,發佈到App store上面,經過審覈就能夠了。
62.C++和Objective-C的混合使用,如下描述錯誤的是()
A. cpp文件只能使用C/C++代碼
B. cpp文件include的頭文件中,能夠出現objective-C的代碼
C. mm文件中混用cpp直接使用便可
D. cpp使用objective-C的關鍵是使用接口,而不能直接使用代碼
63.如下哪一段代碼不會拋出異常( C& D )
A. NSArray array = @[1, 2, 3];NSNumbernumber = array[3];// @[@1,@ 2,@ 3]
B. NSDictionary *dict = @{@」key」:
nil};//value不能爲空
C. NSString *str = nil; NSString *str2 =[str substringFromIndex:3];
D. NSString *str = @」hi」;NSString *str2 =[str substringFromIndex:3];
64.在沒有navigationController的狀況下,要從一個ViewController切換到另外一個ViewController應該()
A.{self.navigationControllerpushViewController:nextViewController animated:YES};
B.{self .viewaddSubview:nextViewController}
C. {selfpresentModalViewController:nextViewController animated:YES};
D. {selfpushViewController:nextViewController animated:YES};
分析:A、C都須要有navigationController,B一個控制器的view是沒法加載另外一個控制器的view的,因此選C!
65.關於下面線程管理錯誤的是()
//不肯定
A.GCD在後端管理着一個線程池
B.NSOperationQueue是對NSthread的更高層的封裝,對
C.NSThread須要本身管理線程的生命週期
D.GCD能夠根據不一樣優先級分配線程,對
66.iOS中的數據持久化方式(D)
A.屬性列表
B.對象歸檔
C.SQLite和CoreData
D.以上所有+對象歸檔
67.設有一下宏定義:
則執行語句: Y(5 + 1)爲:(26)
68.以下程序用於把"blue"字符串返回,請指出其中的錯誤.
//不肯定
char *GetBlue() { char *pcColor; char*pcNewColor; pcColor = 「blue」; pcNewColor =(char*)malloc(strlen(pcColor)); strcpy(pcNewColor, pcColor); return pcNewColor; }
答:strcpy是一個字符串拷貝的函數,它的函數原型爲strcpy(char *dst, c*****t char *src);將src開始的一段字符串拷貝到dst開始的內存中去,結束的標誌符號爲'\0',因爲拷貝的長度不是由咱們控制的,因此這個字符串拷貝很容易出錯
69.常見的object-c的數據類型有哪些,和C的基本數據類型有什麼區別?如:NSInteger和int
答:object的數據類型由NSString,NSNumber,NSArray,NSMutableArray,NSData等等,這些都是class,建立後即是對象,而C語言的基本數據類型int,只是必定字節的內存空間,用於存放數值,NSInteger是基本的數據類型,並非NSNumber的子類,固然也不是NSObject的子類。NSInteger是基本數據類型int或者Long的別名(NSInteger的定義typedef long NSInteger)它的區別在於,NSInteger會根據系統是32位仍是64位來決定是自己int仍是long.
70.iOS有垃圾回收機制嗎?它是以怎樣的機制來工做的?
答: OC是支持垃圾回收機制的(Garbage collection簡稱GC),可是apple的移動終端中,是不支持GC的,Mac桌面系統開發中是支持的.
移動終端開發是支持ARC(Automatic
Reference Counting的簡稱),ARC是在IOS5以後推出的新技術,它與GC的機制是不一樣的。咱們在編寫代碼時,不須要向對象發送release或者autorelease方法,也不能夠調用delloc方法,編譯器會在合適的位置自動給用戶生成release消息(autorelease),ARC的特色是自動引用技術簡化了內存管理的難度.
71.請使用gcd完成以下任務,執行併發任務task1,task1完成後update UI.
答:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ //task1: NSLog(@"執行task1"); //更新UI dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"更新UI"); }); });
72.爲何在主線程中更新UI?子線程中想要更新UI怎麼作?
答:(1)在子線程中不能更新UI,除了極少數UI外,其餘UI更新要等到子線程執行完畢後回到主線程中進行更新。若是子線程一直在運行,則子線程中UI更新的函數棧主線程沒法得知,即UI沒法更新;
(2)回到主線程中進行UI更新;
73.簡述經過Storyboard實現一個tableView
(自定義cell的關鍵步驟).
答:首先建立本身的自定義cell的類,咱們叫作CustomCell,要繼承於UITableViewCell。在這個類中定義本身所須要的控件。
而後,打開storyboard,選擇本身要添加自定義cell的UIViewController,咱們叫它爲ViewController。在UITableView裏面添加一個cell(或者修改原有的cell)。將cell的style改成custom,將cell的類改成CustomCell,將identifier改成CustomCellIdentifier。而後,能夠在cell中添加控件,將控件和剛纔在CustomCell中定義的控件連起來。
最後,在ViewController的UITableView的tableView:cellForRowAtIndexPath:代理方法中添加如下代碼:
[plain]
CustomCell*cell=[tableViewdequeueReusableCellWithIdentifier:@"CustomCellIdentifier"];
這樣,就建立了一個cell,能夠在這句代碼以後對本身添加的控件進行設置。
74.如何生成同時支持多個架構(simulator,arm7,arm64)的通用靜態庫?
答:ValidArchitectures設置爲:armv7|armv7s|arm64|i386|x86_64;
Architectures設置不變(或根據你須要):armv7|arm64;
而後分別選擇iOS設備和模擬器進行編譯,最後找到相關的.a進行合包,使用lipo -create真機庫.a的路徑模擬器庫.a的的路徑-output合成庫的名字.a;
這樣就製做了一個通用的靜態庫.a;
75.請寫出一個xml文件,用於描述一個書架,書架上有2本書,書本的類別(category)分別是cooking,children.要求tag中包含書名(title),做者(author).類別(category)要用屬性表示.
答:
書名1<\title> 做者1<\author> <\book> 書名2<\title> 做者2<\author> <\book>
76.strcpy和memcpy的最大區別是什麼?
答:一、複製的內容不一樣。strcpy只能複製字符串,而memcpy能夠複製任意內容,例如字符數組、整型、結構體、類等。
二、複製的方法不一樣。strcpy不須要指定長度,它遇到被複制字符的串結束符"\0"才結束,因此容易溢出。memcpy則是根據其第
3個參數決定複製的長度。
三、用途不一樣。一般在複製字符串時用strcpy,而須要複製其餘類型數據時則通常用memcpy
108.g++, ld是什麼?聲明編譯選項–DSUPPORT_BLUETOOTH =
1有什麼做用?
答: g++是GNU的c++編譯器;
77.@class用途
答:@class通常用於頭文件中聲明某個類的實例變量的時候用到.它只是聲明,至於內部的實現是沒有告訴編譯器的.
78.delegate使用assign or retain簡述理由.
答:assign,防止出現循環引用;
79.NSString與NSData之間的轉換過程當中要特別注意的事項是什麼?
解:
NSString轉換成NSData對象 NSData* xmlData = [@"testdata"dataUsingEncoding:NSUTF8StringEncoding]; NSData轉換成NSString對象 NSData * data; NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSData轉換成char* NSData *data; char *test=[data bytes]; char*轉換成NSData對象 byte* tempData = malloc(sizeof(byte)*16); NSData *content=[NSData dataWithBytes:tempData length:16];
轉換過程當中要注意NSData的編碼格式問題.
解決方法:
先設置斷點而後在控制檯po出NSData的變量,看看會顯示什麼。
若是po出的NSData是可閱讀的,直接能看到文本的內容,則使用[NSString stringWithFormat:NSData] (這裏的NSData指的是你須要轉換成NSString的NSData變量)便可。
若是po出的NSData是不可閱讀的亂碼,那通常都是有編碼格式的,最經常使用的是NSUTF8StringEncoding,另外還有NSASCIIStringEncoding等,你能夠在Apple文檔裏找到編碼格式的那個枚舉類型,挨個嘗試。
80.請用代碼如何判斷某個對象obj是否支持某個method.
解:
if ([srespondsToSelector:@selector(print:)]) { [s print:@"支持這個方法"]; }
81.請用簡單的代碼展現@protocol的定義及實現.
解:
#warning代理第一步:聲明協議 @protocol MarryMe -(void)makeMoney; @end #warning代理第二步:聲明代理 @property(nonatomic,assign)id myDeleget; .m文件中 #warning代理第三步:代理人執行協議方法 [self.myDeleget makeMoney]; 代理人.m文件中 #warning代理第四步:簽定協議 @interface Boy : NSObject Girl *girl = [[Girl alloc] init]; #warning代理第五步:成爲代理人 girl.myDeleget = self; [girl getMessage:message]; #warning協議代理第六步:實現協議方法 -(void)makeMoney{ NSLog(@"aaa"); }
82.請描述應聘崗位的將來職業規劃
解:答案不惟一,若有須要請自行規劃活着百度.
83.3升的杯子一個,5升的杯子一個,杯子的形狀不規則,問怎麼才能獲得4升的水,水無限多.(請寫出推理過程)
解:先將5升的杯子倒滿,而後把5升的杯子中的水倒入3升的杯子,倒滿後5升的杯子剩下2升.再把3升杯子中的水倒掉,把5升的杯子中剩餘的2升水倒入3升的杯子中,而後把5升的杯子倒滿.再用5升的杯子中的水給3升的杯子添滿,則5升的杯子中剩餘4升的水.
84.數據持久化存儲方案有哪些?
解:所謂的持久化,就是將數據保存到硬盤中,使得在應用程序或機器重啓後能夠繼續訪問以前保存的數據。在iOS開發中,數據持久化的方案有5種方案:
plist文件(屬性列表)
preference(偏好設置)
NSKeyedArchiver(歸檔)
SQLite 3
CoreData
85.網絡通訊用過哪些方式?
解: ios設備的網絡通訊的方法,有以下兩個大類:
一、使用socket的方式進行通訊。
二、使用asynsocket類庫進行通訊。
86.如何處理多個網絡請求併發的狀況?
解: //瞭解(併發)當有多個線程在操做時,若是系統只有一個CPU,則它根本不可能真正同時進行一個以上的線程,它只能把CPU運行時間劃分紅若干個時間段,再將時間段分配給各個線程執行,在一個時間段的線程代碼運行時,其它線程處於掛起狀。.這種方式咱們稱之爲併發(Concurrent)。
遇到這種狀況建議使用第三方的網絡庫。好比AFNetworking。也能夠經過GCD和NSOperationQueue來控制併發
87.簡單介紹一下KVC和KVO,他們均可以應用在哪些場景?
解: KVO:鍵值監聽,觀察某一屬性的方法
KVC:鍵值編碼,是一種間接訪問對象的屬性
88.講述一下runtime的概念,messagesend若是尋找不到響應的對象,會如何?
Objc Runtime實際上是一個Runtime庫,它基本上是用C和彙編寫的,這個庫使得C語言有了面向對象的能力。
89. iOS可否嵌入其餘語言?如何實現?
90. iOS移動開發最終生成的是什麼文件?其結構如何?
最後打包完成是一個.ipa文件能夠經過iTunes和其餘工具對有測試資格的手機進行安裝
91. UINavigationController如何要使用push/pop功能的話,須要怎麼實現
1.用UINavigationController的時候用pushViewController:animated
----返回以前的視圖[[selfnavigationController] popViewControllerAnimated:YES];
---ps:push之後會在navigation的left bar自動添加back按鈕,它的響應方法就是返回。因此通常不須要寫返回方法,點back按鈕便可。
2.其餘時候用presentModalViewController:animated
[selfpresentModalViewController:controller animated:YES];//YES有動畫效果
-----返回以前的視圖[selfdismissModalViewControllerAnimated:YES];
3.切換視圖通常用不到addSubview
UINavigationController是導航控制器,若是pushViewController的話,會跳轉到下一個ViewController,點返回會回到如今這個ViewController;
若是是addSubview的話,其實仍是對當前的ViewController操做,只是在當前視圖上面又「蓋」住了一層視圖,其實原來的畫面在下面呢,看不到而已。
92. UIView如何須要從新繪製整個界面,須要調用什麼方法?
UIView setNeedsDisplay和setNeedsLayout方法。首先兩個方法都是異步執行的。而setNeedsDisplay會調用自動調用drawRect方法,這樣能夠拿到UIGraphicsGetCurrentContext,就能夠畫畫了。而setNeedsLayout會默認調用layoutSubViews,就能夠處理子視圖中的一些數據。
綜上所述:setNeedsDisplay方便繪圖,而layoutSubViews方便出來數據
setNeedDisplay告知視圖它發生了改變,須要從新繪製自身,就至關於刷新界面.
93. Plist文件?結構是?
Plist文件一般用於儲存用戶設置,也能夠用於存儲捆綁的信息,該功能在舊式的Mac OS中是由資源分支提供的。
Plist主要有Core Fundation類型構成,也能夠將這些類型放入NSDictionary和NSArray以便後塍更復雜的數據類型
94. iOS裏面的二進制數據類型是什麼?和NSString如何互相轉換?
NSData:用於存儲二進制的數據類型
NSData類提供了一種簡單的方式,它用來設置緩衝區、將文件的內容讀入緩衝區,或將緩衝區的內容寫到一個文件。
不變緩衝區(NSData類),也可定義可變的緩衝區(NSMutableData類)。
NSData、NSString互轉:
NSData * data = [str dataUsingEncoding:NSUTF8StringEncoding];
//NSString轉換成NSData類型
NSString * newStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
95. iOS裏面是否有GBK的字符編碼描述?即NSUTF8StringEncoding若是有,是怎樣的?
96. iOS裏面的手勢是如何實現的?
97.談談你瞭解的設計模式,你用過哪些,他們的缺點
1.MVC:優勢:
一、開發人員能夠只關注整個結構中的其中某一層;
二、能夠很容易的用新的實現來替換原有層次的實現;
三、能夠下降層與層之間的依賴;
四、有利於標準化;
五、利於各層邏輯的複用。
缺點:
一、下降了系統的性能。這是不言而喻的。若是不採用分層式結構,不少業務能夠直接造訪數據庫,以此獲取相應的數據,現在卻必須經過中間層來完成。
二、有時會致使級聯的修改。這種修改尤爲體如今自上而下的方向。若是在表示層中須要增長一個功能,爲保證其設計符合分層式結構,可能須要在相應的業務邏輯層和數據訪問層中都增長相應的代碼。
2.觀察者模式優勢:
一、觀察者模式在被觀察者和觀察者之間創建一個抽象的耦合。被觀察者角色所知道的只是一個具體觀察者列表,每個具體觀察者都符合一個抽象觀察者的接口。被觀察者並不認識任何一個具體觀察者,它只知道它們都有一個共同的接口。
因爲被觀察者和觀察者沒有緊密地耦合在一塊兒,所以它們能夠屬於不一樣的抽象化層次。若是被觀察者和觀察者都被扔到一塊兒,那麼這個對象必然跨越抽象化和具體化層次。
二、觀察者模式支持廣播通信。被觀察者會向全部的登記過的觀察者發出通知,
觀察者模式缺點:
一、若是一個被觀察者對象有不少的直接和間接的觀察者的話,將全部的觀察者都通知到會花費不少時間。
二、若是在被觀察者之間有循環依賴的話,被觀察者會觸發它們之間進行循環調用,致使系統崩潰。在使用觀察者模式是要特別注意這一點。
三、若是對觀察者的通知是經過另外的線程進行異步投遞的話,系統必須保證投遞是以自恰的方式進行的。
四、雖然觀察者模式能夠隨時使觀察者知道所觀察的對象發生了變化,可是觀察者模式沒有相應的機制使觀察者知道所觀察的對象是怎麼發生變化的。
3.單例模式:主要優勢:
一、提供了對惟一實例的受控訪問。
二、因爲在系統內存中只存在一個對象,所以能夠節約系統資源,對於一些須要頻繁建立和銷燬的對象單例模式無疑能夠提升系統的性能。
三、容許可變數目的實例。
3.單例模式:主要缺點:
一、因爲單利模式中沒有抽象層,所以單例類的擴展有很大的困難。
二、單例類的職責太重,在必定程度上違背了「單一職責原則」。
三、濫用單例將帶來一些負面問題,如爲了節省資源將數據庫鏈接池對象設計爲的單例類,可能會致使共享鏈接池對象的程序過多而出現鏈接池溢出;若是實例化的對象長時間不被利用,系統會認爲是垃圾而被回收,這將致使對象狀態的丟失.
98.數據持久化存儲方案有哪些?
答:
(附網址:http://www.cocoachina.com/industry/20130328/5908.html)
iOS中的數據持久化方式,基本上有如下四種:屬性列表、對象歸檔、SQLite3和Core Data
1.屬性列表(NSUserDefaults,用於存儲配置信息)
涉及到的主要類:NSUserDefaults,通常[NSUserDefaults standardUserDefaults]就夠用了
2.對象歸檔
要使用對象歸檔,對象必須實現NSCoding協議.大部分Object C對象都符合NSCoding協議,也能夠在自定義對象中實現NSCoding協議,要實現NSCoding協議,實現兩個方法
3.SQLite3
SQLite的數據庫權限只依賴於文件系統,沒有用戶賬戶的概念。SQLite有數據庫級鎖定,沒有網絡服務器。它須要的內存,其它開銷很小,適合用於嵌入式設備。你須要作的僅僅是把它正確的編譯到你的程序。
4.Core Data
Core Data本質上是使用SQLite保存數據,可是它不須要編寫任何SQL語句。
要使用Core Data,須要在Xcode中的數據模型編輯器中設計好各個實體以及定義好他們的屬性和關係。以後,經過操做這些對象,結合Core Data完成數據的持久化:
99.網絡通訊用過哪些方式?
(附網址:http://blog.csdn.net/chang6520/article/details/7967698)
一樣也是代碼解釋
iOS設備的網絡通訊的方法,有以下兩個大類:
一、使用socket的方式進行通訊。
以TCP爲利,對於TCP來講,是要區分服務端和客戶端的。服務端:一般的方法是服務端啓動後監聽,是否有客戶端鏈接,若是有鏈接,則創建與客戶端的通訊。客戶端的方法一般是鏈接服務端,當鏈接成功以後,就但願發送數據了。
二、使用asynsocket類庫進行通訊。
100.如何處理多個網絡請求併發的狀況?
答:
(附網址:http://www.cnblogs.com/yanhuaxuanlan/p/4683557.html)
答案都是代碼,你們能夠打開網址仔細閱讀
1.併發當有多個線程在操做時,若是系統只有一個CPU,則它根本不可能真正同時進行一個以上的線程,它只能把CPU運行時間劃分紅若干個時間段,再將時間段分配給各個線程執行,在一個時間段的線程代碼運行時,其它線程處於掛起狀。.這種方式咱們稱之爲併發(Concurrent)。
2.並行當系統有一個以上CPU時,則線程的操做有可能非併發。當一個CPU執行一個線程時,另外一個CPU能夠執行另外一個線程,兩個線程互不搶佔CPU資源,能夠同時進行,這種方式咱們稱之爲並行(Parallel)。
3.區別併發和並行是即類似又有區別的兩個概念,並行是指兩個或者多個事件在同一時刻發生;而併發是指兩個或多個事件在同一時間間隔內發生。
101.簡單介紹一下KVC和KVO,他們均可以應用在哪些場景?
答:
(附網址:http://blog.csdn.net/zhaozy55555/article/details/8598374
http://www.cnblogs.com/kenshincui/p/3871178.html)
KVC:NSKeyValueCoding的簡稱,是一種能夠直接經過字符串的名字(key)來訪問類屬性的機制,而不是經過調用的Setter、Getter方法訪問。
KVC的操做方法由NSKeyValueCoding協議提供,NSObject就實現了這個協議,也就是說若是對象是NSObject的子對象那麼就支持KVC操做,KVC有兩種操做方法,一種是設值,一種是取值,能夠理解爲getter和setter,不過稍微有所不一樣的是,設置對象值的方法中有兩個,setValue:屬性值forKey:屬性名(通常的設置,好比說是說設置NSString,NSNumber等基本類類型,setetValue:屬性值forKeyPath:屬性路徑
2.KVO:NSKeyValueObserving的簡稱,當指定的對象的屬性被修改了,容許對象接受到通知的機制。每次指定的被觀察對象的屬性被修改的時候,KVO都會自動的去通知相應的觀察者,至關於設計模式中的觀察者模式。
Key-Value Observing (KVO)創建在KVC之上,可以觀察一個對象的KVC key path值的變化,接下來的作的實例是在iOS中視圖的ViewDidLoad中實現的,跟KVC相似,不過能夠監聽值的變化,實現起來很簡單addObserver添加觀察,observeValueForKeyPath觀察變化以後的事件,最後須要銷燬如下監聽事件,
須要完整PDF文檔,可進入小編iOS交流羣:624212887,羣文件直接獲取,更多技術書籍,面試資料盡在此,歡迎入駐,交流探討