面試題總結
-
1、#import 跟#include、@class有什么區別?#import<> 跟 #import”"又什么區別?
-
include和#import都能完整的包含某個文件的內容,#import可以防止一個文件被導入多次。@class只是聲明一個類名,並不會包含包含類的完整聲明,@class可以解決循環包含的問題。
include通常是用來包含系統自帶的文件,而import則是用來包含自己自定義的文件。 -
import會包含這個類的所有信息,包括實體變量和方法,而@class只是告訴編譯器,其后面聲明的名稱是類的名稱,至於這些類是如何定義的,暫時不用考慮,后面會再告訴你。
-
在頭文件中, 一般只需要知道被引用的類的名稱就可以了。 不需要知道其內部的實體變量和方法,所以在頭文件中一般使用@class來聲明這個名稱是類的名稱。 而在實現類里面,因為會用到這個引用類的內部的實體變量和方法,所以需要使用#import來包含這個被引用類的頭文件。
-
在編譯效率方面考慮,如果你有100個頭文件都#import了同一個頭文件,或者這些文件是依次引用的,如A–>B, B–>C, C–>D這樣的引用關系。當最開始的那個頭文件有變化的話,后面所有引用它的類都需要重新編譯,如果你的類有很多的話,這將耗費大量的時間。而是用@class則不會。
-
如果有循環依賴關系,如:A–>B, B–>A這樣的相互依賴關系,如果使用#import來相互包含,那么就會出現編譯錯誤,如果使用@class在兩個類的頭文件中相互聲明,則不會有編譯錯誤出現。
所以,一般來說,@class是放在interface中的,只是為了在interface中引用這個類,把這個類作為一個類型來用的。 在實現這個接口的實現類中,如果需要引用這個類的實體變量或者方法之類的,還是需要import在@class中聲明的類進來.
-
-
2、屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那種情況下用?
-
readwrite--同時生成get方法及set方法的聲明和實現。
-
readonly--只生成get方法的聲明和實現。
-
assign--set方法的實現是直接賦值,用於基本數據類型。
-
retain--set方法的實現是release舊值,retain新值,用於OC對象。
-
copy--set方法的實現是release舊值,copy新值,用於NSString,Block類型
-
nonatomic--非原子性,set方法的實現不加鎖(atomic主要加的是自旋鎖)
-
unsafe_unretained 用unsafe_unretained聲明的指針,指針指向的對象一旦被釋放,這些指針將成為野指針
-
-
3、寫一個setter方法用於完成@property (nonatomic,retain)NSString *name,寫一個setter方法用於完成@property(nonatomic,copy)NSString *name.
- (void)setName:(NSString *)name { if (_name != name) { //release舊值 [_name release]; _name = [name copy]; } } - (void)setName:(NSString *)name { if (_name != name) { [_name release]; _name = [name retain]; } }
-
4、對於語句NSString*obj = [[NSData alloc] init]; ,編譯時和運行時obj分別是什么類型?(待補充)
-
編譯時是NSString類型,執行時是NSData類型。
-
runtime是一個C語言框架,蘋果底層就是這個,
-
-
5、常見的object-c的數據類型有那些, 和C的基本數據類型有什么區別?
- object-c的數據類型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,這些都是class,創建后便是對象,而C語言的基本數據類型int,只是一定字節的內存空間,用於存放數值;NSInteger是基本數據類型,並不是NSNumber的子類,當然也不是NSObject的子類。NSInteger是基本數據類型Int或者Long的別名(NSInteger的定義typedef long NSInteger),它的區別在於,NSInteger會根據系統是32位還是64位來決定是本身是int還是Long。
-
6、id聲明的變量有什么特性
-
id聲明的對象能指向任何OC對象
-
用於修飾代理,
-
id相當於NSObject *
-
-
7、Objective-C如何對內存管理的,說說你的看法和解決方法?
-
Objective-C內存管理主要有三種方式,MRC(Manual Reference Counting )和ARC(Automatic Reference Counting)、自動釋放池
-
每個對象都有一個引用計數,當他被alloc init出來時,引用計數為1,然后retain一次加1,release減1,當引用計數為0時,系統就會自動調用delloc方法,在delloc方法中[super delloc]必須寫,這個對象就會被回收。
-
Autorelease-自動釋放池,在iOS運行過程中,會創建無數個池子,這些池子都是以棧型結構存儲的,當一個對象調用autorelease 系統會把該對象放到棧頂的自動釋放池中,當自動釋放池銷毀的時候,系統會對池子中的所有對象進行一次release操作,系統自帶的方法中,如果不包含alloc copy new,那么這些方法的返回對象都是autorelease的,如[NSData data].
-
自動釋放池的創建方式
-
iOS 5之前
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
-
iOS 5之后
@autoreleasepool {//開始代表創建自動釋放池 ······· }//結束代表銷毀自動釋放池
-
-
ARC--只要沒有強指針指向的對象,對象就會被釋放,強指針__strong ,屬性中的strong相當於MRC中的retain,弱指針__weak,屬性中的weak相當於assign,成員變量是弱指針,ARC不允許調用retain release retainCount方法,可以重寫delloc方法,但是不允許調用[super delloc]方法。
-
-
8、看下面的程序,三次NSLog會輸出什么?為什么?
NSMutableArray* ary = [[NSMutableArray array] retain]; NSString *str = [NSString stringWithFormat:@"test"]; // 1 [str retain]; // 2 [ary addObject:str]; // 3 NSLog(@"%d", [str retainCount]); [str retain]; // 4 [str release]; // 3 [str release]; // 2 NSLog(@"%d", [str retainCount]); [ary removeAllObjects]; // 1 NSLog(@"%d", [str retainCount]);
- str的retainCount創建+1,retain+1,加入數組自動+1
3 - retain+1,release-1,release-1
2 - 數組刪除所有對象,所有數組內的對象自動-1
1
- str的retainCount創建+1,retain+1,加入數組自動+1
-
9、內存管理的幾條原則時什么?按照默認法則.那些關鍵字生成的對象
需要手動釋放?在和property結合的時候怎樣有效的避免內存泄露?- 誰申請,誰釋放
- 遵循Cocoa Touch的使用原則;
- 內存管理主要要避免“過早釋放”和“內存泄漏”,對於“過早釋放”需要注意@property設置特性時,一定要用對特性關鍵字,對於“內存泄漏”,一定要申請了要負責釋放,要細心。
- 關鍵字alloc 或new 生成的對象需要手動釋放;
- 設置正確的property屬性,對於retain需要在合適的地方釋放,
-
10、Object C中創建線程的方法是什么?如果在主線程中執行代碼,方法是什么?如果想延時執行代碼、方法又是什么?
-
線程創建有三種方法:使用NSThread創建、使用GCD的dispatch、使用子類化的NSOperation,然后將其加入NSOperationQueue;
-
在主線程執行代碼,方法是performSelectorOnMainThread,如果想延時執行代碼可以用performSelector:onThread:withObject:waitUntilDone:
-
-
11、ViewController的didReceiveMemoryWarning怎么被調用?
- [supper didReceiveMemoryWarning];
-
12、什么時候用delegate,什么時候用Notification?
-
Delegate是一種點對點的消息傳送機制。傳遞給自己或者其他對象。有時候他還會返回一個影響事件如何被處理的值。
在內存管理環境中,delegate是弱引用。在垃圾回收環境中,delegate是強引用。 -
Notification是一種一對多的消息傳遞方式。他的實質是廣播信息給所有observer。消息發送者不需要知道誰是消息的接收者。
他減少了對象之間的依賴。
-
-
13、深拷貝和淺拷貝
淺拷貝
//創建一個可變的數組 NSMutableArray *array = [NSMutableArray array]; //創建兩個person對象,然后把他們加入到數組中 Person *p1 = [[Person alloc]init]; p1.name = @"小玉"; Person *p2 = [[Person alloc]init]; p2.name = @"小小玉"; [array addObject:p1]; [array addObject:p2]; //淺拷貝 NSArray *newArray = [array copy]; Person *p = newArray[0]; p.name = @"小王八"; //輸出array[0]和newArray[0],結果發現他兩輸出都為小王八, NSLog(@"array = %@ newArray = %@",((Person *)array[0]).name,((Person *)newArray[0]).name);
深拷貝
//創建一個可變的數組 NSMutableArray *array = [NSMutableArray array]; //創建兩個person對象,然后把他們加入到數組中 Person *p1 = [[Person alloc]init]; p1.name = @"小玉"; Person *p2 = [[Person alloc]init]; p2.name = @"小小玉"; [array addObject:p1]; [array addObject:p2]; NSMutableArray *newArray = [NSMutableArray array]; for (Person *p in array) { Person *p2 = [[Person alloc]init]; p2.name = p.name; [newArray addObject:p2]; } Person *person = newArray[0]; person.name = @"小王八"; //輸出為小王八 NSLog(@"%@",((Person *)newArray[0]).name); //輸出為小玉 NSLog(@"%@",((Person *)array[0]).name);