一、基礎面試題
1. #import 跟 #include、@class有什麼區別?#import<> 跟 #import""又什麼區別?
- #import 和 #include 都能完整的包含某個文件的內容,#import 能防止同一個文件被包含多次
- @class 僅僅聲明一個類名,並不會包含類的完整聲明;@class還能解決循環包含的問題
- #import<> 用來包含系統自帶的文件,#import" " 用來包含自定義的文件
2. 屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什麼作用,在那種情況下用?
- readwrite:讀寫特性,同時生成getter 和 setter 方法的聲明和實現
- .readonly:只讀特性,只生成 getter 方法的聲明和實現
- assign:set 方法的實現直接賦值,用於基本數據類型
- retain:set 方法的實現是 release 舊值, retain 新值,用於 OC 對象類型
- copy : set 方法的實現是 release 舊值,copy 新值 ,用於 NSString、block 等類型
- nonatomic:非原子性,set 方法的實現不加鎖,不安全,性能高(atomic 性能低,atomic 通過鎖定機制來確保其原子性,但只是讀/寫安全,不能絕對保證線程的安全,當多線程同時訪問的時候,會造成線程不安全,可以是線程鎖來保證線程的安全)
3. 寫一個setter方法用於完成@property (nonatomic,retain)NSString *name,寫一個setter方法用於完成@property(nonatomic,copy)NSString *name.
1> @property (nonatomic, retain) NSString *name;
- (void)setName:(NSString *)name
{
if (_name != name) {
[_name release];
_name = [name retain];
}
}
2> @property(nonatomic, copy) NSString *name;
- (void)setName:(NSString *)name
{
if (_name != name) {
[_name release];
_name = [name copy];
}
}
4. 對於語句NSString*obj = [[NSData alloc] init]; ,編譯時和運行時obj分別是什麼類型?
- 編譯時是NSString類型
- 運行時是NSData類型
5. 常見的object-c的數據類型有那些, 和C的基本數據類型有什麼區別?如:NSInteger和int
- OC常見的數據類型:NSString、NSArray、NSDictionary、NSData、NSNumber等
- OC對象需要手動管理內存,C的基本數據類型不需要管理內存
- NSInteger 是基本數據類型,並不是NSNumber 的子類,當然也不是NSObject的子類
- NSInteger 是基本數據類型 Int 或者 Long 的別名(NSInteger 的定義 typedef long NSInteger),它的區別在於NSInteger 會根據系統是 32 位還是64 位來決定其本身是 int 或者是 long。
6. id 聲明的變量有什麼特性?
- id 聲明的變量指向任何 OC 對象
7. Objective-C如何對內存管理的,說說你的看法和解決方法?
- 每個對象都有一個引用計數器,每個新對象的計數器是1,當對象的引用計數爲0時,就會被銷燬
- 通過 retain 可以讓引用計數器 +1 ,release 可以讓引用計數器 -1
- 還可以通過 autorelease 管理內存
- 如果是 ARC,編譯器會自動生成管理內存的代碼
注意:不管是 MRC 還是 ARC 都是在編譯時完成的
8. 內存管理的幾條原則時什麼?按照默認法則.哪些方法生成的對象需要手動釋放?在和property結合的時候怎樣有效的避免內存泄露?
- 只要調用了 alloc、copy、new 方法產生的新對象,都必須在最後調用一次 release 或者是 autorelease
- 只要調用了 retain ,都必須在最後調用一次 release 或者 autorelease
- @property 如果用 copy 或者 retain ,就需要對不再使用的屬性做一次 release 操作
9. 看下面的程序,三次NSLog會輸出什麼?爲什麼?
NSMutableArray* ary = [[NSMutableArray array] retain];
NSString *str = [NSString stringWithFormat:@"test"];
[str retain];
[ary addObject:str];
NSLog(@"%ld", (unsigned long)[str retainCount]);
[str retain];
[str release];
[str release];
NSLog(@"%ld", (unsigned long)[str retainCount]);
[ary removeAllObjects];
NSLog(@"%ld", (unsigned long)[str retainCount]);
結果:-1、-1、-1。-1代表沒有引用計數或者引用計數非常大,因爲str 是字符串,字符串在常量區,沒有引用計數。引用計數爲 -1,這可以理解爲 NSString 實際上是一個字符串常量,是沒有引用計數的(或者它的引用計數是一個很大的值(使用 %lu 可以打印查看)),對它做引用計數操作實際上沒有任何影響
10. OC中創建線程的方法是什麼?如果指定在主線程中執行代碼?如何延時執行代碼?
1> 創建線程的方法有:NSThread、CGD、NSOperation
2> 主線程中執行代碼
[self performSelectorOnMainThread: withObject: waitUntilDone:];
[self performSelector: onThread:[NSThread mainThread] withObject: waitUntilDone:];
dispatch_async(dispatch_get_main_queue(), ^{
});
3> 延時操作
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
});
[self performSelector: withObject: afterDelay:];
[NSTimer scheduledTimerWithTimeInterval: target: selector: userInfo: repeats:];
11.淺拷貝與深拷貝的區別?
- 淺拷貝:對指針進行拷貝,不會產生新的對象
- 深拷貝:對指針和指針指向的內容進行拷貝,會生成新的對象
12.分類的作用是什麼?實現類別和繼承有什麼區別?
- 分類可以在不修改原有類模型的基礎上擴充方法
- 分類只能擴充方法,不能擴充成員變量;繼承可以擴充方法和成員變量
- 繼承會產生新的類
13. 分類和擴展的區別?
- 分類是有名稱的,類擴展是沒有名稱的
- 分類只能擴充方法,不能擴充成員變量;類擴展可以擴充方法和成員變量
- 類擴展一般寫在 .m 文件中,用來擴充私有的方法和成員變量
14.OC 中的協議和 Java 中的接口概念有什麼不同?
- Java 的接口中聲明的方法必須都實現
- OC 中 protocol 中聲明的方法並一定要實現
15.什麼是 KVC 和 KVO?
- KCV 是鍵值編碼,可以通過一個字符串的 key(屬性名)修改對象的屬性的值
- KVO 是鍵值監聽,可以監聽一個對象屬性值的改變
16.代理的作用是什麼?
- 兩個對象之間傳遞數據和消息
- 解耦,拆分業務邏輯
17.OC 中可修改和不可修改的類型?
- mutable 是可以變類型,比如 NSMutableArray ,可以動態添加元素
- immutable 是不可變類型,比如 NSArray, 固定的存儲空間,不能添加元素
18.爲什麼說 OC 是動態運行時語言?
- 動態綁定:對象類型在運行時才能真正確定
- 多態性(不同對象以自己的方式去響應相同的消息的能力)
- 消息機制
19.通知和協議有什麼不同之處?
- 通過 NSNotification 可以給多個對象傳遞數據和消息
- 通過 protocol 只能給一個對象傳遞數據和消息
20.什麼是推送消息?
- 本地推送:程序內部彈出的通知到用戶設備
- 遠程推送:有推送服務器推送通知到用戶設備
21.什麼是多態?
- 多態:父類指針指向子類對象
22.怎麼理解單例?
- 單例:保證程序運行過程中,永遠只有一個對象實例
- 作用:全局共享一份資源、節省不必要的內存開銷
23.怎麼理解響應鏈?
- 事件響應鏈:包括點擊事件、畫畫刷新事件等。
- UIResponder 有一個 nextResponder 屬性,通過該屬性可以組成一個響應者鏈,事件或消息在其路徑上進行傳遞
- 如果 UIResponder 沒有處理傳給它的事件,會將未處理的消息轉發給自己的 nextResponder
24.frame 和 bounds 有什麼區別?
- frame:以父控件的左上角爲座標原點
- bounds:以控件本身的左上角爲座標原點
25.方法和選擇器有什麼不同?
- selector:是一個方法的名稱,通過 selector 可以找到方法地址,進而調用這個方法
- method:是一個組合體,包含名字和實現
26.OC 的垃圾回收機制?
- OC 1.0沒有垃圾回收
- OC 2.0有垃圾回收,但只能用在mac上
- iOS 中有 ARC機制,是編譯器特性,垃圾回收是運行時特性
27.什麼是NSOperation queue?
- 用來存放 NSOperation 對象的隊列,可以用來異步執行一些操作
- 一般可以用在網絡請求等耗時操作
28.什麼是懶加載(延遲加載)?
- 延遲加載:比如控制器的 view ,在第一次用到 view 時纔會調用 loadView方法進行創建
29.是否在一個控制器中嵌入兩個 tableView 控制器?
- 技術角度上,一個控制器添加兩個list 是沒有問題的
30.一個 tableView 是否可以關聯兩個不同的數據源?
- 從對象屬性上分析,tableView只有一個dataSource屬性。當然,真要使用2個不同的數據源,還是有其他辦法解決的
31.什麼時候用 NSMutableArray?什麼時候用NSArray?
- 當數組元素需要動態添加或者刪除時用可變數組
- 當數組元素固定不變是用不可變數組
32.在應用中可以創建多少autorelease對象,是否有限制?
- 沒有限制
33.如果我們不創建內存池,是否有內存池提供給我們?
- 系統會默認會不定時地創建和銷燬自動釋放池
34.什麼時候需要在程序中創建內存池?
- 用戶自己創建的數據線程,則需要創建該線程的內存池
35.什麼時候內存計數會增加?
- 當做一次 retain 或者是 copy 操作的時候,內存引用計數都會增加1
36.類NSObject的那些方法經常被使用?
- NSObject是Objetive-C的基類,其由NSObject類及一系列協議構成。
- NSObject 常見的類方法有:alloc、class、 description 對象方法init、dealloc、– performSelector:withObject:afterDelay:等經常被使用
37.什麼是簡便構造方法?
- 簡便的構造方法一般由 Cocoa Touch 框架提供,如 NSNumber 的 + numberWithBool: + numberWithChar: + numberWithDouble: + numberWithFloat: + numberWithInt:
- Foundation 下部分類均有簡便構造方法,我們可以通過簡便構造方法獲取系統給我們創建好的對象,並且不需要手動釋放。
38.如何使用Xcode設計通用應用?
- 使用MVC模式設計應用,其中Model層完成脫離界面,即在Model層,其是可運行在任何設備上,在controller層,根據iPhone與iPad(獨有UISplitViewController)的不同特點選擇不同的viewController對象。在View層,可根據現實要求,來設計,其中以xib文件設計時,其設置其爲universal。
39.在Objetive-C什麼時原子關鍵字?
- atomic:原子性,會對 setter 方法的實現進行加鎖
40.UIView的動畫效果有那些?
有很多,如
UIViewAnimationOptionCurveEaseInOut
UIViewAnimationOptionCurveEaseIn
UIViewAnimationOptionCurveEaseOut
UIViewAnimationOptionTransitionFlipFromLeft
UIViewAnimationOptionTransitionFlipFromRight
UIViewAnimationOptionTransitionCurlUp
UIViewAnimationOptionTransitionCurlDown
41.在iPhone應用中如何保存數據?
- 屬性列表
- NSUserDefault
- 鍵值歸檔(NSKeyedArchiver、NSCoding)
- SQLite 數據庫
- Core Data
42.什麼是NSManagedObject模型?
- NSManagedObject 是 NSObject 的子類 ,也是 Core Data 的重要組成部分,它是一個通用的類,實現了Core Data 模型層所需的基本功能,用戶可通過子類化 NSManagedObject,建立自己的數據模型。
43.什麼是謂詞?
謂詞是通過NSPredicate,是通過給定的邏輯條件作爲約束條件,完成對數據的篩選。
predicate = [NSPredicate predicateWithFormat:@"customerID == %d",n];
a = [customers filteredArrayUsingPredicate:predicate];
44.OC 有多繼承嗎?沒有的話用什麼代替?
- OC 是單繼承,沒有多繼承
- 可以用分類或者是協議來代替多繼承
45.OC 有私有方法嗎?私有變量呢?
- OC 沒有類似 @private 的修飾詞來修飾方法,只要寫在 .h 文件中,就是公共方法
- 如果不在 .h 文件中聲明,只在 .m 文件中實現,或在 .m 文件的 Class Extension 裏面聲明,那麼基本上和私有方法差不多,可以使用類擴展 來增加私有方法和私有變量
- 使用 @private 修飾的全局變量是私有變量
46.關鍵字 const 什麼含義?
const int a;
int const a;
const int *a;
int const *a;
int * const a;
int const * const a;
1.前面兩個的作用是一樣的:a 是一個常整形數
2.第三、四個意味着 a 是一個指向常整型數的指針(整型數是不可修改的,但是指針可以)
3.第五個意思:a 是一個指向整型數的常指針(指針指向的整型數是可以修改的,但是指針是不可修改的)
4.最後一個意思:a 是一個指向常整型數的常指針(指針指向的整型數是不可修改的,同時指針也是不可修改的)
47.static 的作用?
- static 修飾的函數是一個內部函數,只能在本文件中調用,其他文件不能調用
- static 修飾的全局變量是一個內部變量,只能在本文件中使用,其他文件不能使用
- static 修飾的局部變量只會初始化一次,並且在程序退出時纔會回收內存
48.線程和進程的區別?
- 一個應用程序對應一個進程,一個進程幫助程序佔據一塊存儲空間。也有多個進程應用(如瀏覽器)
- 要想在進程中執行任務,進必須開啓線程,一個線程代表一個任務
- 一個進程中允許開啓多條線程,也就是可以同時執行多個任務
49.堆和棧的區別?
- 堆空間的內存是動態分配的,一般存放對象,並且需要手動釋放內存
- 棧空間的內存由系統自動分配,一般存放局部變量等,不需要手動管理內存
50.爲什麼很多內置的類,如TableView 的delegate 的屬性是 assign 而不是 retain?
- tableView 的代理一般都是它所屬的控制器,控制器會對它內部的 view 做一次 retain 操作
- 假設 tableView 也對代理做一次 retain 操作,那麼久會出現循環 retain 問題
51.定義屬性,什麼時候用 copy、assign、retain?
- copy:NSString、Block 等類型
- assign:非 OC 對象類型,基本數據類型(兩個對象相互引用的時候,一端用 retain 一端用 assign)
- retain:OC對象類型
52.對象是什麼時候被釋放的?
- 每個對象都有一個引用計數器,每個新對象的引用計數器都是1,當對象引用計數器爲0時,就會被銷燬
53.tableView的重用機制?
- 這裏只是簡述:將離開屏幕的cell放到緩存池,重新拿來顯示到屏幕的其他位置(其他自己詳細描述)
54.ViewController 的loadView、viewDidLoad、viewDidUnload分別是什麼時候調用的,在自定義ViewCointroller時在這幾個函數中應該做什麼工作?
- loadView:但第一次使用控制器的view時,會調用 loadView 方法創建 view。 一般在這裏自定義 view
- viewDidLoad:當控制器的 view 創建完畢是回調用,也就是在 loadView 後調用。一般在這裏添加子控件、初始化數據
- viewDidUnload:當控制器的 view 因爲內存警告被銷燬是調用。一般在這裏回收跟界面相關的資源(界面都會銷燬了,跟界面相關的資源肯定不要了)
55.ViewController的didReceiveMemoryWarning是在什麼時候調用的?默認的操作是什麼?
- 當程序接收到系統內存警告時,就有可能調用控制器的 didReceiveMemoryWarning 方法
- 它的默認做法是:當控制器的 view 不在窗口上顯示時, 就會直接銷燬,並且調用 viewDidUnload 方法
56.怎麼理解 MVC ,在Cocoa 中MVC 是怎麼實現的?
- M:model,模型 ,封裝數據
- V:view,視圖界面,負責展示數據
- C:Controller,控制器,負責提供數據給界面
57.self. 跟 self -> 有什麼區別?
- self. 是調用 get 方法或者是 set 方法
- self 是當前本身,是一個指向當前對象的指針
- self -> 是直接訪問成員變量
58.id、nil 代表什麼?
- id 類型的指針可以指向任何 OC 對象
- nil 代表空值(空指針的值)
59.如何對 iOS 設備進行性能測試?
- Timer Profile
二、iOS-內存管理
1. 什麼情況使用 weak 關鍵字,相比 assign 有什麼不同?
- 什麼時候使用 weak 關鍵字?
- 在 ARC 中,在有可能出現循環引用的時候,往往要通過讓其中一端使用 weak 關鍵字來解決,如:delegate 代理屬性
- 自身已經對它進行過一起強引用,沒有必要再強引用一次,此時也會使用 weak 關鍵字,自定義 IBOutlet 控件屬性一般也使用 weak ;當然也可以使用 strong 。
- 不同點:
- weak 此特性表明該屬性定義一種 “非擁有關係”。爲這種屬性設置新值時,設置的方法既不保留新值,也不釋放舊值。此特質同 assign 類似,然而在屬性所指的對象遭到摧毀時,屬性值也會清空,而 assign 的設置方法只會針對純量類型(CGFloat、NSInteger)的簡單賦值操作。
- assign 可以用 非 OC對象,爲 weak 必須用於 OC 對象
2.如何讓自己的類用 copy 修飾符?如何重寫帶 copy 關鍵字的 setter?
- 若想讓自己自定義的對象具有copy功能,則需要實現 NSCopying 協議。如果自定的對象分爲可變版本和不可變版本,則需要同時實現 NSCopying 和 NSMutableCopying 協議。
具體步驟:
聲明該類遵從 NSCopying 協議,實現 NSCopying 協議。該協議只有一個方法:
- (id)copyWithZone:(NSZone *)zone;
注意:一提到讓自己的類用 copy 修飾符,我們總是想覆寫copy方法,其實真正需要實現的卻是 “copyWithZone” 方法。
- 重寫帶 copy 關鍵字的 setter 例如:
- (void)setName:(NSString *)name {
_name = [name copy];
}
3.深拷貝與淺拷貝
- 淺拷貝只是針對指針的拷貝,拷貝後兩個指針指向同一個內存空間。
- 深拷貝不但對指針進行拷貝,而且對指針指向的內容進行拷貝,經深拷貝後的指針是指向兩個不同地址的指針。
- 但對象中存在指針成員時,除了在複製對象時需要考慮自定義拷貝構造函數,還應該考慮以下兩種情況:1.當函數的參數爲對象時,實參傳遞給形參的實際上是實參的一個拷貝對象,系統自動通過拷貝構造函數實現;2.當函數的返回值爲一個對象時,該對象實際上是函數內對象的一個拷貝,用於返回函數調用處。copy 方法:如果是非可擴展類對象,則是淺拷貝。如果是可擴展類對象,則是深拷貝。mutableCopy 方法:無論是可擴展對象還是不可擴展對象,都是深拷貝。
持續更新。。。。 歡迎指導