注:以下的內容是我自己面試遇到的或者是在網上找到的,然后自己總結了下,不恰當的地方請指正,萬分感激!!
1.如果設計一個秒表的APP
為了防止手指在觸摸屏幕的時候停止跳動,一般會用到哪個類?
一般會用到 NSRunLoop類?????
2.如果需要持久化對象,需要實現的協議是:
實現的協議是NSCoding的協議。// 歸檔和結歸檔。
NSCoding Delegate Method
- (void)encodeWithCoder:(NSCoder *)aCoder {
// 進行編碼操作
[aCoder encodeObject:_instance forKey:@"_intance.key"];
}
- (void)initWithCoder:(NSCoder *)aDecoder {
// 進行解碼操作
if (self = [super init]) {
self.instance = [aDecoder decodeObjectForKey:@"_instance.key"];
}
return self;
}
3.UIApplication類幫助我們運行Maps,sms,瀏覽器或其他程序的時候用的方法是:- (BOOL)openURL:(NSURL*)url;
openURL:方法,/*'URL'就是統一資源定位符。*/
UIApplication類有個功能十分強大的openURL:方法
- (BOOL)openURL:(NSURL*)url;
openURL:方法的部分功能有
// 打電話:
UIApplication *app = [UIApplication sharedApplication];
[app openURL:[NSURL URLWithString:@"tel://10086"]];
//發短信 :
[app openURL:[NSURL URLWithString:@"sms://10086"]];
// 發郵件 :
[app openURL:[NSURL URLWithString:@"mailto://12345@qq.com"]];
// 打開一個網頁資源:
[app openURL:[NSURL URLWithString:@"http://ios.cn"]];
打開其他app程序:openURL方法,可以打開其他APP。
4.在viewController中,init loadView viewWillAppear等的執行順序。
執行的順序為:
->init方法:執行關鍵數據初始化操作,注意這里不要做view相關操作
->loadView->viewDidLoad->viewWillAppear->viewWillLayoutSubviews->viewDidLayoutSubviews->viewDidAppear->viewWillDisappear->viewDidDisappear->viewWillUnload->viewDidUnload。
5.performSelector:withObject:方法的作用是什么?
簡而言之就是程序在運行的時候去找方法,而不在編譯的時候找方法。如果寫了一個方法卻不存在,直接調用執行這個方法,會在編譯的時候報錯,而如果使用performSelector進行調用的話,不會再編譯的時候報錯,而是在程序運行的時候進行報錯而導致崩潰。
5.Socket和HTTP的區別 (TCP/IP)
http://blog.csdn.net/zeng622peng/article/details/5546384
a.HTTP:
HTTP連接最顯著的特點是客戶端發送的每次請求都需要服務器回送響應,在請求結束后,會主動釋放連接。從建立連接到關閉連接的過程稱為“一次連接”。
由于HTTP在每次請求結束后都會主動釋放連接,因此HTTP連接是一種“短連接”,要保持客戶端程序的在線狀態,需要不斷地向服務器發起連接請求。通常的做法是即時不需要獲得任何數據,客戶端也保持每隔一段固定的時間向服務器發送一次“保持連接”的請求,服務器在收到該請求后對客戶端進行回復,表明知道客戶端“在線”。若服務器長時間無法收到客戶端的請求,則認為客戶端“下線”,若客戶端長時間無法收到服務器的回復,則認為網絡已經斷開。
b.Socket
c.區別
很多情況下,需要服務器端主動向客戶端推送數據,保持客戶端與服務器數據的實時與同步。此時若雙方建立的是Socket連接,服務器就可以直接將數據傳送給客戶端;若雙方建立的是HTTP連接,則服務器需要等到客戶端發送一次請求后才能將數據傳回給客戶端,因此,客戶端定時向服務器端發送連接請求,不僅可以保持在線,同時也是在“詢問”服務器是否有新的數據,如果有就將數據傳給客戶端。
注:
TCP/IP的三從握手:
HTTP連接最顯著的特點是客戶端發送的每次請求都需要服務器回送響應,在請求結束后,會主動釋放連接。從建立連接到關閉連接的過程稱為“一次連接”。
手機能夠使用聯網功能是因為手機底層實現了TCP/IP協議,可以使手機終端通過無線網絡建立TCP連接。TCP協議可以對上層網絡提供接口,使上層網絡數據的傳輸建立在“無差別”的網絡之上。
建立起一個TCP連接需要經過“三次握手”:
第一次握手:客戶端發送syn包(syn=j)到服務器,并進入SYN_SEND狀態,等待服務器確認;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。
握手過程中傳送的包里不包含數據,三次握手完畢后,客戶端與服務器才正式開始傳送數據。理想狀態下,TCP連接一旦建立,在通信雙方中的任何一方主動關閉連接之前,TCP 連接都將被一直保持下去。斷開連接時服務器和客戶端均可以主動發起斷開TCP連接的請求,斷開過程需要經過“四次握手”(過程就不細寫了,就是服務器和客戶端交互,最終確定斷開)
6.polymorphism(多態)
多態就是多個對象想要你同一個方法的時候有著不同的結果,這就是多態,這都要用到繼承的。
7.為什么很多內置類如UITableViewController的delegate的屬性都是用的assign而不是retain。
首先如果使用了retain的話,會造成循環引用。
如果控制器的有個對象a持有tableView的對象b,而恰好b的delegate又持有a,而如果delegate的屬性是retain的話,那么在a想要釋放的時候,a所持有的b是不會被釋放,因而a也得不到釋放,所以為了避免循環引用,要用assign。
8.在一個對象的方法里面:self.name = "object";和name = "obeject";有什么不同。
1.self.name:是會調用name的setName()方法。
2.name:會直接把object賦值給當前對象的name屬性。
9.如何實現深拷貝
http://www.cocoachina.com/ios/20141113/10213.html
首先拷貝分為深拷貝和淺拷貝;
1.淺拷貝:只復制指向對象的指針,而不復制引用的對象本身,是通過復制對象的指針來訪問指針。
char* str = (char*)malloc(100);
char* str2 = str;
2.深拷貝:復制的是對象本身。加入A修改了,而A_Copy是不會被修改的。
默認遵守了NSCopying和NSMutableCopying協議的可以有
NSString *string = @”dddd";
NSString *stringCopy = [string copy];
NSMutableString *stringDCopy = [string mutableCopy];
[stringMCopy appendString:@"!!"];
以上的代碼得知,string和stringCopy的指向的地址是一致的,值也固然是一致的,但是如果更改了string的值,string的地址會改變,而stringCopy的地址和值均不改變。
但是如果沒有遵守這兩個協議的,也是可以構造。還是得遵守NSCopying協議和實現copyWithZone:方法。
#pragma mark - 協議的遵守
@interface MyObj : NSObject<NSCopying, NSMutableCopying>{
NSMutableString *_name;
NSString * _imutableStr ;
int _age;
}
@property (nonatomic, retain) NSMutableString *name;
@property (nonatomic, retain) NSString *imutableStr;
@property (nonatomic) int age;
#pragma mark - Copy的構造
- (id)copyWithZone:(NSZone *)zone{
MyObj *copy = [[[self class] allocWithZone :zone] init];
copy->name = [_name copy];
copy->imutableStr = [_imutableStr copy];
copy->age = age;
return copy;
}
#pragma mark - MutableCopy的構造
- (id)mutableCopyWithZone:(NSZone *)zone{
MyObj *copy = NSCopyObject(self, 0, zone);
copy->name = [_name mutableCopy];
copy->age = age;
return copy;
}
9.JSON和XML解析的原理
區別:
1.XML和JSON的可讀性都基本相同,但是XML的可讀性比較好。
2.可擴展性:兩者都具有很好的擴展性,
3.編碼難度:JSON的編碼比較容易
4.解碼難度:JSON的解碼難度基本為0,XML需要考慮到子節點和父節點
5.數據體積:JSON相對XML而言體積小,傳遞速度更快
6.數據交互:JSON和JS的交互更加方便,更好的解析出來,更好的數據交互
7.數據描述:XML對數據描述性比較好
JSON解析原理
遍歷字符串中的字符,最終根據格式規定的特殊字符,比如:
{}
[]
:
等進行區分,
{}
:是一個字典的開始
[]
:是一個數組的開始
:
:字典的鍵 值 的區別
最終將JSON數據轉化為字典,字典中的值可能是數組或者是字符串。
XML的解析原理
常用的解析方式是兩種:DOM解析和SAX解析
DOM常用建立樹形結構的方式訪問XML文檔,DOM解析把XML文檔轉化為包含其內容的樹,并且可以對樹進行遍歷。使用DOM解析的時候,需要處理整個XML文檔,所以對性能和內存的要求比較高;
SAX采用的是事件模型,SAX解析XML文檔時可以觸發一系列事件,當發現給定的tag值之后,可以激活一個回調方法,告訴該方法制定的tag已經找到,SAX對于內存的要求比較低。
10.什么是簡便構造方法
- (instancetype)init
{
self = [super init];
if (self) {
<#statements#>
}
return self;
}
初始化對象(分配空間并且初始化)
作用:
用作初始化對象的成員變量.
把 C 語言指針初始化為 NULL
把 OC 對象初始化為 nil
把基本數據類型初始化為0
11.什么是謂詞
Predicate
謂詞就相當于指定過濾器的條件。創建NSPredicate對象,這個對象可以準確的描述需要的條件,通過謂詞篩選每個對象,就可以判斷它們是否與條件相匹配
原理類似于在數據庫中進行查詢。
12.在項目中,什么時候使用GCD什么時候使用NSOperation
GCD一般做異步處理 。NSOperation一般是多個操作,可以方便的控制異步的執行數量,如下載任務。
兩者的區別:
1.GCD:是APPLE為多核的并行運算提出的解決方案,他會自動利用更多的CPU內核,可以自動管理線層的生命。GCD是純C語言的API,任務是用塊來表示的,而塊是個輕量級的數據結構。
2.NSOperation:他是oc的對象,operation是個重量級的oc對象,而且NSOperation和NSOperationQueue的好處如下:
a.取消某個操作
b.指定操作間的依賴關系
c.通過鍵值觀測機制監控NSOperation對象的屬性
d.指定操作的優先級
e.重用NSOperation對象。
13.什么是block,block實現原理。
1.塊也就是我們所說的block,塊與函數類似,只不過是直接定義在另一個函數里的,和定義在那個函數共享一個范圍內的東西。block是用“^”表示的,后面跟著一對花括號,括號里面的是現實代碼。例如:
^ {
// block implementation is here
}
block其實就是一個值,自己有其相關的類型,也可以像int類型等把block賦值給變量。
void (^someBlock)() = ^ {
// block implementation is here
};
這里的block類型的語法結構如下:
return_type (^block_name)(parameters)
2.block是可以分配在棧上或堆上的,也可以是全局的,分配在棧上的block是可以通過copy函數copy到堆上的(深拷貝),這樣就具備了和oc對象一樣的引用計數了。
3.block的實現原理
在oc引入塊之前,要實現相同的功能的,就需要傳入函數的指針或選擇子的名稱,提供給其他的方法進行調用。
而block在內存中的結構為isa、flags、reserved、invoke、discriptor。而isa也是指向Class對象的指針;在內存中最為重要的是invoke變量,這個函數指針指向block中的現實代碼。而descriptor變量指向的是結構體的指針,其中申明了block對象的總體大小;這里還有兩個輔助函數對應的指針,分別是copy和dispose,copy是要保留捕獲的對象,而dispose是講捕獲的對象進行釋放。
block是可以拿到所在函數范圍內所有東西,所以在block里可以拿到被捕獲的變量,但是默認是不能夠對變量進行修改的,如需要進行修改是要加上__block
修飾符的。
14.談談對響應鏈的理解
事件響應鏈:
包括了點擊事件,畫面刷新事件等,在試圖棧內從上至下,或從下至上傳播,可以說點事件的分發,傳遞及處理(具體的看Touch事件)
首先解釋下響應者鏈的概念:
A.UIResponder類,是UIKit中一個用于處理事件響應的基類。窗口上所有事件觸發都有該類響應(即事件處理入口),所有窗口上的View和控制器UIViewController都是其派生類。
B.調用UIResponder類提供的方法或熟悉,我們就可以捕捉到窗口上的所有響應事件,并且進行處理。
C.響應者鏈條是由多個響應者對象連接起來的鏈條,其中響應者對象是能處理事件的對象,所有的view和VC都是響應對象,利用響應者鏈條可以讓多個控件處理同一個觸摸事件。
事件傳遞機制:
如果當前的view不能處理當前事件,那么事件將會沿著響應者鏈
(Responder Chain)進行傳遞,直到遇到能處理該事件的響應者(Responder Object)。
接收事件的initial view如果不能處理該事件并且自己也不是頂層的View,則事件會往他的父類view進行傳遞
initial view的父視圖獲取事件如果還是不能處理,則會繼續往上傳遞,循環這個過程。如果頂層的view還是不能處理這個事件的話,則事件會傳遞給她們的控制器VC。
如果VC也不能處理,則傳遞給UIWindow,此時UIWindow還是不能處理的話,就傳遞給UIApplication,如果UIApplication還是不能處理的話,這個事件就會被廢棄掉。
注:事件的分發和以上的過程是相反的。事件分發主要是找到事件能夠被處理的對象。
15.frame和bounds有什么區別
frame的位置和大小是以本個視圖的父視圖為基準的。
bounds的位置和大小是本個試圖為基準的。
16.寫一個標準的宏MIN,這個宏輸入兩個參數,并返回較小的一個
#define MIN(a,b) ((a)>(b)?(b):(a)) // 三元運算
17.說一說對NSRunLoop的理解。
Runloop 是什么?Runloop 還是比較顧名思義的一個東西,說白了就是一種循環,只不過它這種循環比較高級。一般的 while 循環會導致 CPU 進入忙等待狀態,而 Runloop 則是一種“閑”等待。當沒有事件時,Runloop 會進入休眠狀態,有事件發生時, Runloop 會去找對應的 Handler 處理事件。Runloop 可以讓線程在需要做事的時候忙起來,不需要的話就讓線程休眠。
幾乎每個講 Runloop 的文章都會引用的圖,大體說明了 Runloop 的工作模式:
圖中展現了 Runloop 在線程中的作用:從 input source 和 timer source 接受事件,然后在線程中處理事件。
Runloop 和線程是綁定在一起的。每個線程(包括主線程)都有一個對應的 Runloop 對象。我們并不能自己創建 Runloop 對象,但是可以獲取到系統提供的 Runloop 對象。
主線程的 Runloop 會在應用啟動的時候完成啟動,其他線程的 Runloop 默認并不會啟動,需要我們手動啟動。
18.nil,Nil,NULL,NSNull的區別
1.nil
和 C 語言的 NULL
相同,在 objc/objc.h
中定義。nil
表示 Objective-C 對象的值為空。在 C 語言中,指針的空值用 NULL
表示。在 Objective-C 中, nil
對象調用任何方法表示什么也不執行,也不會崩潰。
2.Nil
:那么對于我們 Objective-C 開發來說,Nil
也就代表((void *)0)
。但是它是用于代表空類的. 比如:Class myClass = Nil;
3.NULL
: 在 C 語言中,NULL
是無類型的,只是一個宏,它代表空. 這就是在 C/C++中的空指針。對于我們 Objective-C 開發來說, NULL 就表示((void*)0)
.
4.? NSNull
:NSNULL
是繼承于 NSObject 的類型。它是很特殊的類,它表示是空,什么也不存儲,但是它卻是對象,只是一個占位對象。使用場景就不一樣了,比如說服務端接口中讓我們在值為空時,傳空。
NSDictionry *parameters = @{@"arg1" : @"value1",@"arg2" : arg2.isEmpty ? [NSNull null] : arg2};
? NULL、 nil、 Nil 這三者對于 Objective-C 中值是一樣的,都是(void *)0,那么為什么要區分呢?又與 NSNull 之間有什么區別:
? NULL 是宏,是對于 C 語言指針而使用的,表示空指針;
? nil 是宏,是對于 Objective-C 中的對象而使用的,表示對象為空;
? Nil 是宏,是對于 Objective-C 中的類而使用的,表示類指向空;
? NSNull 是類類型,是用于表示空的占位對象,與 JS 或者服務端的null 類似的含意。