iOS面試題目

    1 OC中,與alloc語義相反的方法是dealloc還是release?與retain語義相反的方法是dealloc還是release?爲什麼?需要與alloc配對使用的方法是dealloc還是release,爲什麼?

    以下是針對MRC(手動內存釋放)模式:
    與alloc語義相反的方法是dealloc,與retain語義相反的方法是release。
    alloc是爲對象在內存中開闢空間,而dealloc則是對象銷燬時釋放空間。
    retain方法是對象開闢空間以後使對象的引用計數器加1,而release是對象的引用計數器減1。
    需要與alloc配對的方法是release,因爲對象創建以後,對象的引用計數器自動加1,
    而調用release方法後,對象的引用計數器歸0,系統會自動調用dealloc方法釋放空間。

   2. 在一個對象的方法裏面:self.name = @"object";和 _name = @"object"有什麼不同嗎?
           
self.name = @"object"; 是通過點語法修改屬性name的值。
    本質上使用的是name屬性的setter方法進行的賦值操作,實際上執行的代碼是

    [self setName:@"object"];

    例如:
    @property(nonatomic, strong) NSString *name;
    //根據@property關鍵詞,系統自動生成setter方法。
    - (void)setName:(NSString *)name{
        //根據strong關鍵詞
        [name retain];  //內存計數+1
        [_name release];    //把之前指針指向的內容內存計數-1
        _name = name; //指向新內容
    }

    _name = @“object”; 只是單純的把‘_name’指針指向‘@"object"’字符串對象所在的地址,
    沒有調用方法。
 3. 這段代碼有什麼問題嗎?
-(void)setAge:(int)newAge{ 
self.age = newAge; 
}
在age屬性的setter方法中,不能通過點語法給該屬性賦值。
    會造成setter方法的循環調用。因爲self.age = newAge; 
    本質上是在調用 [self setAge:newAge]; 方法。
    解決循環調用的方法是方法體修改爲 _age = newAge;

    另外 變量名稱不能使用new開頭!
4. 簡要敘述面向對象的特點,特別是多態。
1. 封裝
封裝是對象和類概念的主要特性。它是隱藏內部實現,提供外部接口,可以看作是“包裝”。 
封裝,也就是把客觀事物封裝成抽象的類,並且類可以把自己的數據和方法只讓可信的類或者對象操作,
對不可信的進行信息隱藏。
封裝的目的是增強安全性和簡化編程,使用者不必瞭解具體的實現細節,而只是要通過外部接口,
以特定的訪問權限來使用類的成員。
好處:可以隱藏內部實現細節。通過大量功能類封裝,加快後期開發速度。

2. 繼承
面向對象編程 (OOP) 語言的一個主要功能就是“繼承”。
繼承是指這樣一種能力:它可以使用現有類的所有功能,並在無需重新編寫原來的類的情況下
對這些功能進行擴展。
通過繼承創建的新類稱爲“子類”或“派生類”,被繼承的類稱爲“基類”、“父類”或“超類”。
繼承的過程,就是從一般到特殊的過程。在考慮使用繼承時,有一點需要注意,
那就是兩個類之間的關係應該是“屬於”關係。
例如,Employee(僱員)是一個人,Manager(領導)也是一個人,因此這兩個類都可以繼承Person類。
但是 Leg(腿) 類卻不能繼承 Person 類,因爲腿並不是一個人。

3. 多態
多態性(polymorphism)是允許你將父對象設置成爲和一個或更多的他的子對象相等的技術,
賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。
簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。
不同對象以自己的方式響應相同的消息的能力叫做多態。
意思就是假設生物類(life)都用有一個相同的 方法-eat;那人類屬於生物,豬也屬於生物,
都繼承了life後,實現各自的eat,但是調用是我們只需調用各自的eat方法。
也就是不同的對象以 自己的方式響應了相同的消息(響應了eat這個選擇器)。
實現多態,有二種方式,覆蓋,重載。
•    覆蓋(override),是指子類重新定義父類的虛函數的做法。
•    重載(overload),是指允許存在多個同名函數,而這些函數的參數表不同
        (或許參數個數不同,或許參數類型不同,或許兩者都不同)。
** 這裏注意:OC沒有重載,因爲OC只認函數名,不認參數類型。OC不允許存在多個同名函數。

總結:封裝可以隱藏實現細節,使得代碼模塊化;繼承可以擴展已存在的代碼模塊(類);
它們的目的都是爲了——代碼重用。
而多態則是爲了實現另一個目的——接口重用!
多態的作用,就是爲了類在繼承和派生的時候,保證使用“家譜”中任一類的實例的某一屬性時的正確調用。
在類層次中,子類只繼承一個父類的數據結構和方法,則稱爲單重繼承。 
在類層次中,子類繼承了多個父類的數據結構和方法,則稱爲多重繼承。 
5. objective-c 所有對象間的交互是如何實現的?
在對象間交互中每個對象承擔的角色不同,
但總的來說無非就是”數據的發送者”或”數據的接收者”兩種角色。
消息的正向傳遞比較簡單,直接拿到接受者的指針即可。
消息的反響傳遞可以通過委託模式,觀察者模式(本質是單例模式),block語法,AppDelegagte來實現。
其中委託模式,block語法都是1對1的消息傳遞。 觀察者模式是1對多。
AppDelegate比較特殊,這是一個生命週期與進程一致的對象。
6. 什麼叫數據結構?
數據結構是計算機存儲、組織數據的方式。是指相互之間存在一種或多種特定關係的數據元素的集合。
通常,精心選擇的數據結構可以帶來更高的運行或者存儲效率。
7、OC的類可以多繼承嗎?可以實現多個接口嗎?Category是什麼?分類中能定義成員變量或屬性嗎?爲什麼?重寫一個類的方式是繼承好還是類別好?爲什麼?
Object-c的類不可以多重繼承;可以實現多個接口(協議),通過實現多個接口可以完成C++的多重繼承;
Category是類別,推薦使用類別,用Category去重寫類的方法,僅對本引入Category的類有效,
不會影響到其他類與原有類的關係。
8、#import和#include有什麼區別?@class呢?#import<>和#import”“有什麼區別?#import和#include有什麼區別?@class呢?#import<>和#import”“有什麼區別?
#import是Objective-C導入頭文件的關鍵字,#include是C/C++導入頭文件的關鍵字,
使用#import頭文件會自動只導入一次,不會重複導入,相當於#include和#pragma once;
@class告訴編譯器某個類的聲明,當執行時,纔去查看類的實現文件,可以解決頭文件的相互包含;
#import<>用來包含系統的頭文件,#import””用來包含用戶頭文件。
例如:

/* 如果這裏不寫@class,則報錯。 原因是找不到MyVC的定義。因爲代碼執行順序是由上至下的。
當聲明協議MyVCDelegate時, MyVC還沒有聲明。
使用 @class 名稱隨便寫,不管是否存在。 可以自己用代碼嘗試隨意寫個@class 例如:
@class Hello; 
就算項目中根本沒有Hello類,這裏也不會報錯。 因爲只有當項目運行起來,纔會真的去檢查Hello類
是否聲明瞭。
*/

@class MyVC;
@protocol MyVCDelegate <NSObject>
- (void)myVC:(MyVC *)myVC click:(id)sender;
@end
@interface MyVC : BaseVC
@end

ps:iOS7之後的新特性,可以使用@import 關鍵詞來代理#import引入系統類庫。
    使用@import引入系統類庫,不需要到build phases中先添加添加系統庫到項目中。

9、寫一個setter方法用於完成@property(nonatomic, strong)NSString *name, 寫一個setter方法用於完成@property(nonatomic, copy)NSString *name
- (void)setName:(NSString*)str //retain
 {
  [str retain];
  [_name release];
  _name = str;
 }
- (void)setName:(NSString *)str //copy
 {
  id t = [str copy];
  [_name release];
  _name = t;
 }
10、對於語句NSString *obj = [[NSData alloc] init]; obj在編譯時和運行時分別是什麼類型的對象?
編譯時是NSString的類型;運行時是NSData類型的對象。
11、常見的OC的數據類型有哪些? 和C的基本數據類型有什麼區別? 如:NSInteger和int
object-c的數據類型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等。

C語言的基本數據類型int,只是一定字節的內存空間,用於存放數值;
NSInteger類型的定義是

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) 
|| TARGET_OS_WIN32  || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else   
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

可以看到,在64位操作系統上,NSInteger是 C語言的long類型。 
在32位操作系統上,則是int類型。
12、id聲明的對象有什麼特性?
id 聲明的對象具有運行時的特性,即可以指向任意類型的objcetive-c的對象;
可以作爲返回值,也可以聲明對象。
例如
- (id)initWithName:(NSString *)name;
id obj = [NSObject new];

現在我們使用蘋果推薦使用的“instancetype”類型代替id類型作爲返回值
- (instancetype)initWithName:(NSString *)name;

instancetype和id的區別在於, id可以聲明對象 也可以作爲返回值,
instancetype只能作爲返回值。
13、OC如何對內存管理的,說說你的看法和解決方法。
Objective-C的內存管理主要有三種方式ARC(自動內存計數)、手動內存計數、內存池。
  1. 自動內存計數ARC:由Xcode自動在App編譯階段,在代碼中添加內存管理代碼。
  2. 手動內存計數MRC:遵循內存誰申請,誰添加。誰釋放的原則。
  3. 內存釋放池Release Pool:把需要釋放的內存統一放在一個池子中,當池子被抽乾後(drain)
    池子中所有的內存空間也被自動釋放掉。 內存池的釋放操作分爲自動和手動。
     自動釋放受runloop機制影響。
14、你對@interface中的成員變量和@property聲明的屬性的理解。
@interface AA: NSObject{
    NSString *_name; //成員變量
}
@property NSString *sex; //屬性

如上所示:
屬性擁有setter和getter方法 外加_sex成員變量。
_name只是成員變量, 沒有setter和getter方法。
15、淺拷貝和深拷貝的區別?
淺拷貝:只複製指向對象的指針,而不復制引用對象本身。 
深拷貝:複製引用和對象本身。 
意思就是說我有個A對象,複製一份後得到A_copy對象後, 
對於淺複製來說,A和A_copy指向的是同一個內存資源,複製的只不過是是一個指針, 
對象本身資源還是隻有一份。 
那如果我們對A_copy執行了修改操作,那麼發現A引用的對象同樣被修改, 
這其實違背了我們複製拷貝的一個思想。 
深複製就好理解了,內存中存在了兩份獨立對象本身。
 
用網上一哥們通俗的話將就是:
 
淺拷貝好比你和你的影子,你完蛋,你的影子也完蛋
 
深拷貝好比你和你的克隆人,你完蛋,你的克隆人還活着。
16、類別的作用?繼承和類別在實現中有何區別?
Category可以向類中添加新的方法,或者重寫已有方法。
正常情況下不可以添加屬性。但是實際應用中可以通過runtime機制添加屬性。
類別主要有3個作用:
- 將類的實現分散到多個不同文件或多個不同框架中。降低耦合性。
- 重寫主類方法
- 向類中添加協議,屬性,方法。

繼承主要作用:
- 重寫父類方法
- 在父類基礎上增加屬性,方法,協議

區別:繼承使用時,需要使用子類。 Category使用時只需要引入頭文件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章