Objective-C關鍵知識點

介紹了Objective-C 的一些關鍵知識點,包括點訪問方法,strong 和weak 的比較,nil,實例化,動態綁定技術(程序在執行時纔會知道要執行的代碼有沒有),自省(選擇器的使用),基礎的框架如NSObject,NSString 等等。

這些是開發的基礎,整理了一遍有利於程序的開發和調整。像類方法只能使用類來調用,實例方法只能使用實例,這點以前還沒有明白。對於在實例中怎麼不能調用類方法的問題還疑惑了一陣子。

 

、點符號方法訪問屬性變量

在property 引進後開始使用這個方法,蘋果官方解釋爲這樣做是出於代碼美觀考慮。蘋果的產品將美觀放在第一位,這產品包括了obj-c 的代碼。

使用點符號法self.propery 訪問@property 比普通的[self property] 方法更直觀。在C 結構體中,也是使用點符號方法訪問屬性。這兩個方法看上去很相似,但它們有兩點大不同:

其一,我們不能發送消息給C 結構體,因爲C 結構體根本沒有可執行的方法。

其二,C 結構體絕不分配在heap 中,因此不能通過指針來訪問到它。(注,它分配在stack 中。內存管理中分爲heap 和stack )

 

2 、 strong  和   weak

在定義@property 時,會有選項如strong 、weak 等。

strong 表示保存這個對象在heap 中直到不再有任何指針指向它。(注,我理解爲所有指向它的指針不先設置爲nil ,它就不會從heap 中清理。)

weak 表示保存這個對象在heap 中,只要其他人strongly 指向了它。如果它從heap 中清理了,會將所有指向它的指針調整爲指向nil 。這個功能從iOS5 開始使用。(注,我理解爲如果它從heap 中清理後,所有指向它的指針都會自動調整爲nil 。)

但是這種清理heap 的機制不是垃圾回收機制,在iOS 上沒有這種內存自動回收機制。它採用的一種更好的機制,稱之爲引用計算(reference counting )。這種機制可以展開來講很多,但在iOS 中又有了新機制,稱爲自動應用計算(ARC) 。瞭解它可以有助於理解內存管理。

在iOS 中還有一種內存釋放方法,爲dealloc 。

- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

這種方法很少會用到,因爲如果用到它,則太遲了。估計iOS 已經將應用給殺死了。

 

3 、 nil

這是一個對象指針的值,表示不指向任何對象。它和原始類型如int double 的“zero “很相似。

在實例變量中,作爲一個對象指針類型定義的,其初始值都是nil 。如

id obj = nil;
NSString *hello = nil;

 nil 還有一個隱藏的功能,就是它可以放在if 語句中做條件判斷。

如if (obj) {run something;} 這個語句,obj 爲nil 時則不執行,不爲nil 則執行。

對於指針值爲nil 的實例變量,任何調用該對象中方法,都不會出錯,沒有任何方法會被執行。這可以理解爲向nil 發送消息時,沒得執行啊。

該操作的返回值是0 。如果int i = [obj methodWhichReturnsAnInt]; 則沒有問題,返回結果是0 ,屬於int 類型;如果CGPoint p = [obj getLocation]; 則就有問題了,返回結果還是0 ,而0 不是CGPoint 類型。CGPoint 是一個C 結構體。(注,類型不一致,會不會crash? )

 

、 BOOL 類型

在Objective-C ,也有一種布爾類型,實質上它是typedef 。

它可以用來做條件判斷

if (flag) { }

if (!flag) { }

YES 值意思爲true ,NO 值意思爲false

N0 值等於0 ,YES 值除0 之外所有的數字

 

 

5 、實例方法和類方法

這個知識點很重要,在obj-c 中使用範圍很廣。他們之間區別有下列幾點需要說明。

第一,命名方式上的差別,實例方法是以“- ”開始,類方法是以“+ ”開始。

- (BOOL)dropBomb:(Bomb *)bomb at:(CGPoint)position from:(double)altitude;// 這是實例方法在.h文件中的聲明

+ (id) alloc;// 這是類方法

+ (Ship *)motherShip;

+ (NSString *)stringWithFormat:...

 

第二,調用語法的差別。

實例方法只能實例去調用,語法爲[<pointer to instance> method] 。

例子:

Ship *ship = ...; // instance of a Ship

destroyed = [ship dropBomb:firecracker at:dropPoint from:300.0];

同樣,類方法只能用類去調用,語法爲[Class method] 。

例子:

Ship *ship = [Ship motherShip];//Ship 是一個類

NSString *resultString =[NSString stringWithFormat:@“%g”, result];//NSString 也是一個類型

[[ship class] doSomething];//ship 是一個實例化的對象,必須使用[ship class] 轉換成類後才能調用類方法,而直接使用ship 實例無法調用到類方法。

(注,首字符爲大寫的都是類,小寫的則是實例化的對象,這是命名規則)

 

第三,self/super 的區別

在類中,使用self/super 的結果都是類;

在實例中,使用self/super 的結果都是實例;

 

 

6 、實例化( Instantiation )

其一,使用其他對象創建自己的對象,如

NSString’s - (NSString *)stringByAppendingString:(NSString *)otherString;

NSString’s & NSArray’s - (id)mutableCopy;

NSArray’s - (NSString *)componentsJoinedByString:(NSString *)separator;

其二,也不是所有的使用其他對象創建而生成的對象都是新建的,有的對象會只是一個指針,而不是在heap 中再劃分內存創建對象。如,

NSArray’s - (id)lastObject;

NSArray’s - (id)objectAtIndex:(int)index;

但是,如果使用copy 關鍵字,則會創建新對象。

其三,還可以使用類方法創建對象,如

NSString’s + (id)stringWithFormat:(NSString *)format, ...

UIButton’s + (id)buttonWithType:(UIButtonType)buttonType;

NSMutableArray’s + (id)arrayWithCapacity:(int)count;

NSArray’s + (id)arrayWithObject:(id)anObject;

 

其四,使用Allocating  和  initializing 創建新對象

例如:

NSMutableArray *stack = [[NSMutableArray alloc] init];

CalculatorBrain *brain = [[CalculatorBrain alloc] init];

Allocating 是通過NSObject 的類方法alloc 在heap 中分配一個空間給新對象。如@synthesize 就是執行這個操作。因此所有的@sythesize 的對象都已經在heap 中分配了一個足夠大的內存空間。但這只是第一步,如果要使用該對象,還必須初始化,否則會直接crash 。

Initializing 對於多數類而言,都有很多方法,但NSObject 類只有一個初始化方法爲init 。

例如:

- (id)initWithFrame:(CGRect)aRect; // initializer for UIView

UIView *myView = [[UIView alloc] initWithFrame:thePerfectFrame];

 

- (id)initWithCharacters:(const unichar *)characters length:(int)length;

- (id)initWithFormat:(NSString *)format, ...;

- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding;

 

在開發類時,初始化方法中的返回類型建議設置成id ,這樣做是爲了繼承。如果它的子類使用它的初始化方法時,直接使用id 類型即可。

例如:

@implementation MyObject

- (id)init

{

self = [super init]; // call our super’s designated initializer

if (self) {

// initialize our subclass here

}

return self;

}

@end

 

7 、動態綁定

其一,所有的對象都被分配在heap 中,所以你一直可以使用指針

例如:

NSString *s = ...; //  靜態類型定義

id obj = s; //  非靜態類型定義,但完全合法,不要使用”id *” 因爲它表示一個指針的指針。

 

其二,在runtime 時纔會知道運行的代碼是什麼

靜態類型如第一點所說的NSString * 和id 的比較,靜態類型只不過在編譯時更有利於我們發現bug 。

如果runtime 時,沒有找到所運行的代碼,就crash 。但我們可以使用“introspection ”去判斷代碼是否可以執行。

 

8 、自省( introspection )

自省是對象的固有能力,即程序運行時,對象可根據請求對外透露自身基本特性。您可以給對象發送某種消息,向其詢問與它自身相關的問題,對象在Objective-C  運行時將會向您提供答案。自省是很重要的編碼工具,它可以讓程序變得更加高效健壯。

所有的繼承了NSObjec 的對象有擁有下列三個方法:“

isKindOfClass: returns whether an object is that kind of class (inheritance included)

isMemberOfClass: returns whether an object is that kind of class (no inheritance)

respondsToSelector: returns whether an object responds to a given method

方法1 的參數值爲[NSString class] ,即發送一個名爲class 的類方法給一個類而得到。例如:

if ([obj isKindOfClass:[NSString class]]) {

NSString *s = [(NSString *)obj stringByAppendingString:@”xyzzy”];

}

 

方法3 的參數值爲一個選擇器,如@selector(shoot) 。

如果對象中有這個方法shoot ,就響應爲true 。例如:

if ([obj respondsToSelector:@selector(shoot)]) {

[obj shoot];

} else if ([obj respondsToSelector:@selector(shootAt:)]) {

[obj shootAt:target];

}

 

介紹一種新類型SEL ,它是Objective-C 用於選擇器的類型。

SEL shootSelector = @selector(shoot);

SEL shootAtSelector = @selector(shootAt:);

SEL moveToSelector = @selector(moveTo:withPenColor:);

 

在NSObject 類中,可以通過方法performSelector:  或者  performSelector:withObject: 來執行選擇器。例如:

[obj performSelector:shootSelector];

[obj performSelector:shootAtSelector withObject:coordinate];

 

在NSArray 類中,可以通過makeObjectsPerformSelector: 來執行選擇器操作。例如:

[array makeObjectsPerformSelector:shootSelector]; // cool, huh?

[array makeObjectsPerformSelector:shootAtSelector withObject:target]; // target is an id

 

在UIButton 類中,可以通過  - (void)addTarget:(id)anObject action:(SEL)action ...; 方法來執行選擇器。例如:

[button addTarget:self action:@selector(digitPressed:) ...];

 

 

9 、基礎框架

NSObject

在IOS SDK 中,NSObject 是基礎類,實現一些方法,如自省的方法等等。

- (NSString *)description is a useful method to override (it’s %@ in NSLog()).

- (id)copy; // not all objects implement mechanism (raises exception if not)

- (id)mutableCopy; // not all objects implement mechanism (raises exception if not)

 

還有這些常用架構,如NSString ,NSMutableString ,NSNumber (原始類型  int, float, double, BOOL 等等的封裝成對象),NSValue ,NSData ,NSDate 。

還有一些集合類型如NSArray ,NSMutableArray ,NSDictionary ,NSMutableDictionary ,NSSet,NSMutableSet ,NSOrderedSet ,NSMutableOrderedSet 。這些分成三種類別,分別爲array,dictionary,set 。

這些類可以使用for in  方法遍歷訪問他們的成員。

還有Property List 和NSUserDefaults 兩個,也需要關注一下。

 

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