前言面試
1. #import和#include的區別?設計模式
參考答案:api
#import是Objective-C導入頭文件的語法,可保證不會重複導入。數組
#include是C/C++導入頭文件的語法,若是是Objective-C與C/C++混編碼,對於C/C++類型的文件,仍是使用#include來引入,這種寫法須要添加防重複導入的語法。安全
2. @class的做用多線程
參考答案:架構
@class通常用於頭文件中經過前向聲明,就能夠聲明瞭,可是在.m文件中仍是須要使用#import進來的。它的做用只是前向聲明。併發
3. 用NSLog函數輸出一個浮點類型,結果四捨五入,並保留一位小數框架
參考答案:
float money = 1.011;
NSLog(@"%.1f", money);
使用%f來格式化,其中要保留一位小數,所以再用%.1f就是保留一位。
4.property屬性的修飾符有什麼樣的做用
參考答案:
property是屬性訪問聲明,擴號內支持如下幾個屬性:
getter=getName、setter=setName:設置setter與getter的方法名
readwrite、readonly:設置可供訪問級別
assign:方法直接賦值,不進行任何retain操做,爲了解決原類型與環循引用問題
retain:其setter方法對參數進行release舊值再retain新值,全部實現都是這個順序
copy:其setter方法進行copy操做,與retain處理流程同樣,先對舊值release,再copy出新的對象,retainCount爲1。這是爲了減小對上下文的依賴而引入的機制。
nonatomic:非原子性訪問,不加同步, 多線程併發訪問會提升性能。注意,若是不加此屬性,則默認是兩個訪問方法都爲原子型事務訪問。
5. self.name=@object和name=@object有什麼不一樣?
參考答案:
self.name =」object」:會調用對象的setName()方法;name = 「object」:會直接把"object"字符串賦值給當前對象的name屬性。
6. viewDidLoad、loadView和viewDidUnload什麼時候調用
參考答案:
viewDidLoad在view加載完成時調用,loadView在controller的view爲nil時調用。對於viewDidUnload如今已經不能直接調用了。
7. objective-c中的可變與不可變詞典
參考答案:
可變字典就是能夠增、刪、改操做的字典,對應於NSMutableDictionary類型。
不可變字典就是不能執行增、刪、改操做的字典,對應於NSDictionary類型。
8.Objective-C的內存管理
參考答案:
如今內存管理幾乎都採用ARC,也就是Automatic Reference Counting,意思是自動引用計數。由編譯器在編譯時自動爲添加retain、release等代碼。
若是問的MRC,也就是Manual Reference Counting,意思是手動內存管理。
黃金法則:誰使對象的引用計數+1,再也不使用該對象時,誰就應該使該對象的引用計數-1。
9. 自動生成getter/setter方法
參考答案:
對於之前的代碼,那時尚未property,使用這樣的方法來建立:
- (void)setName:(NSString *)aName;
- (NSString *)name;
在後面有了property,直接使用@property (nonatomic, copy) NSString *name這樣的方法來聲明,編譯器會自動生成getter/setter方法並生成一個_name成員變量。
10. 什麼是MVC
參考答案:
我相信大部分人在被問到這個問題時,都會回答M就是Model,V就是View,C就是Controller。這都是停留在概念上的回答,明顯沒有什麼工做經驗。對於一個對框架和架構有必定的思想的人,回答時會從項目的耦合度、團隊開發如何減小衝突、如何下降團隊與團隊之間的溝通成本、如何將M、V、C之間按照既定的標準創建溝通的橋樑。
Model用於處理數據,一般來講,Model中會包含多個字段,用於存儲數據。可是,Model還會有一部分邏輯,好比說:
@interface TestModel: HYBBaseModel
// 這個是接口返回的字段,1表示XXX,2表示YYY,3表示ZZZ
@property (nonatomic, assign) NSUInteger type;
// 這個不是接口返回的字段,可是因爲`type`字段是一個數值,不是`view`須要顯示的數據
// 因此咱們最好將邏輯統一放到這裏來,外部只管獲取最終顯示須要的值便可。即便哪天接口
// 返回的字段變化或者增長什麼新的值,只須要處理這個模型內部就行了。
@property (nonatomic, copy, readonly) NSString relationship;
@end
對於View,不該該包含邏輯,應該根據模型直接獲取數據。
對於Controller,大部分交互邏輯都集中到了這裏,全部View須要的數據,都是經過Controller提取Model而後交給view去顯示數據。
11. 重寫getter/setter方法
假設聲明屬性:
@property (nonatomic, copy) NSString *blogName;
重寫這個屬性的getter/setter方法:
參考答案:
這裏一旦連getter方法也重寫,編譯器不會給咱們自動生成成員變量_blogName,所以咱們須要在類的聲明中添加一個成員變量_blogName:
@interface Demo () {
NSString *_blogName;
}
@end
在自動內存管理下(ARC):
- (void)setBlogName:(NSString *)aName {
if (_blogName != aName) {
_blogName = nil;
_blogName = [aName copy];
}
}
- (NSString *)blogName {
return _blogName;
}
對於手動內存管理(MRC):
- (void)setBlogName:(NSString *)aName {
if (_blogName != aName) {
[_blogName release];
_blogName = nil;
_blogName = [aName copy];
}
}
- (NSString *)blogName {
return _blogName;
}
12. obj在編譯時和運行時分別時什麼類型的對象
以下面的代碼,obj在編譯時和運行時分別時什麼類型的對象:
NSString *obj = [[NSData alloc] init];
參考答案:
在編譯時,咱們所聲明的obj是NSString *類型,所以是NSString類型對象。在運行時,因爲指針obj所指向的是NSData類型對象的內存,所以其實是NSData類型的對象。在編譯時,這一行代碼會轉換成相似這樣:
NSString *obj = ((id (*)(id, SEL))objc_msgSend)([NSData class], @selector(alloc));
obj = ((id (*)(id, SEL))objc_msgSend)((id)obj, @selector(init));
因爲在編譯時,轉換成id,所以能夠用NSString *指向NSData對象,而id是具有運行時特性的,所以在連接時,經過id的isa指針能夠找到其所屬的類,所以最終類型仍是經過isa肯定其所屬類型。
13. id聲明的對象有什麼特性?
id類型能夠指向任何類型的對象。
參考答案:
咱們先看看其定義:
/// Represents an instance of a class.
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
可其定義可知id類型是一個指向objc_object結構體類型的指針,這個結構體只有一個指向對象無類的指針isa,所以id能夠指向任何類型的對象,故其具有運行時特性。
14. iOS設備性能測試
在實際開發中,咱們常常須要對應用瘦身,所以對性能的檢測是很重要的。
參考答案:
使用Profile-> Instruments ->Time Profiler能夠檢測性能。
15. Objective-C中有私有方法、私有變量麼?
我記得曾經我就被這麼問過,不知道你們有沒有遇到過。
參考答案:
在類的.m實現文件內聲明,就能夠做爲私有方法、私有變量。可是,並非絕對的私有,若是外部知道有這麼個方法,同樣能夠調用,並且不會報錯。就像蘋果公司沒有公開出來的API,只要咱們經過其它方式瞭解到api就能夠調用。因而蘋果審覈時常常因爲使用了私有api而打回來了。
16. 簡述tableview的重用機制
曾經筆者面試時,也被問到這個問題。
參考答案:
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]
這個方法就是重用機制的核心了。好比,有一個界面可顯示10個cell,那麼建立10次cell,並給cell指定一樣的重用標識(固然,能夠爲不一樣顯示類型的cell指定不一樣的標識)而且10個cell將所有都加入到visiableCells數組,reusableTableCells爲空.
滾動tableView,當有一個cell徹底移出屏幕時,這個cell就會被加入到reusableTableCells。而新出現的那個cell將加入到visiableCells,而這個cell就是被重用的。
若是要讓tableview不重用,不設置reuseIdentifier就能夠了。
17. nil與NULL的區別
參考答案:
nil和C語言的NULL相同,在objc/objc.h中定義。nil表示Objective-C對象的值爲空。在C語言中,指針的空值用NULL表示。在Objective-C中,nil對象調用任何方法表示什麼也不執行,也不會崩潰。
18. Category是什麼,什麼時候使用?
參考答案:
Category就是所謂的擴展。
有時咱們須要在一個已經定義好的類中增長一些方法,而不想去重寫該類,這時候使用擴展就很好。好比,當工程已經很大,代碼量比較多,或者類中已經有不少方法,已經有其餘代碼調用了該類建立對象並使用該類的方法時,可使用類別對該類擴充新的方法。
筆者所到公司之處,都會根據公司的UI風格定製一套UI組件,統一全局的風格。本人向來不喜歡用xib/storyboard開發,由於維護成本過高了。咱們不能經過繼承的方式定製各類組件吧?因此這個時候使用擴展是最佳時期.
19. 什麼是Delegate?經常使用場景?
參考答案:
Delegate就是所謂的代理,代理是一種設計模式。在iOS開發中,會使用到大量的代理,而代理設計模式是蘋果中的標準設置模式。
經常使用場景有反向傳值。好比:蘋果的藍牙,咱們進入到下一個界面去打開或者關閉藍牙,當操做以後須要將狀態反饋到前一個界面,並更新顯示。對於這種狀態,使用代理設計模式是很標準的模式。
20. 什麼是單例,如何設計單例?
參考答案:
單例就是全局都只有一個對象存在,並且是在整個App運行過程當中都存在。每一個App都會有單例,好比UIApplication。而咱們在作用戶數據存儲時,一般都會用單例存儲,由於應用在全部操做中,常常要求先登陸。
下面這種寫法是最經常使用的寫法,這個是線程安全的。
+ (instancetype)shared {
static HYBUserManager *sg_userManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (sg_userManager == nil) {
sg_userManager = [[HYBUserManager alloc] init];
}
});
return sg_userManager;
}
21. 什麼是通知?
參考答案:
在iOS中,通知是很是經常使用的設計模式。它是多對多的關係。關於通知,因爲這一節比較重要,單獨寫成一篇文章,後續發出!
寫在最後
文章中不免有說得不合理的地方,若是您認爲說法不正確或者哪裏有錯誤的地方,請在評論中留言,筆者會在第一時間修正!!!