Objective-C 2.0(三)memory&Foundation Framework Classes:2009年08月19日星期三
在Objective-C 2.0(一)Objects & Messaging的(Q)(R)(S)及Objective-C 2.0(二)Class將Objective-C的Class掃描了一次,每一個主題試作一個SDK 3.0 Xcode上的例子,本文、Objective-C 2.0(三)memory&Foundation Framework Classes,將探討memory及Foundation Framework Classes。這三篇文章將Objective-C Beginner's Guide的中文掃描了一次並參考Objective-C 2.0 Programming Language 及SDK 3.0 Xcode/Help/documentation/SDK3.0 Library ,試做了Objective-C Beginner's Guide的中文所有的例子。這些改寫好的SDK3.0/Xcode例子,已上傳iPhone課程論壇,檔名0816iPhoneStudyGroup.zip及0830iPhoneStudyGroup.zip。
本文的主要根據是Objective-C Beginner's Guide的中文或英文網站,有source code, 下載後稍加修改即可用在Xcode開發環境中(如何改?見Objective-C 2.0(一)Objects & Messaging(Q)(二))。同以Apple的Objective-C 2.0 Programming Language 為輔,在此亦可找到同名的章節Defining a Class、Classes。Language summary也很重要,Class亦在其中。
開始之前先將Objective-C的Language Summary Link放在此。
(A)問:Retain及release是NSObject的protocol,如何使用?詳見Objective-C Beginner's Guide的中文的Retain及release。
答:每個object都有一個reference count,alloc將reference count 設為1,retain將object內的reference count加一,release將object內的reference count減一,當object的reference count減到0時,自動call 該object的dealloc,歸還memory。
型式:
object = [class alloc] // reference count set to 1
[object retain]; // reference count incremented by 1
[object release]; // reference count decremented by 1
[object retainCount]; //return the reference count of the object
說明:見型式內的comment
練習:本段class的練習已作成Xcode可執行的project,名稱為retainObjc。
(B)問:如何使用dealloc?詳見Objective-C Beginner's Guide的中文的dealloc。
答:dealloc一般會release instance variable,並且[super dealloc] 以便free所有super class的memory。
練習:本段class的練習已作成Xcode可執行的project,名稱為deallocObjc。
在練習中,特別注意setFirst內的三行:
[f retain];
[first release];
first =f;
- 這三行的次序不能改變,因f及first均為pointer to object,
- 若先[first release];則first這instance variable就被destruct了。
- 若先first =f;則無法做[first release];以便free first指向的NSString這片memory。
- 因為是pointer assignment,所以需先[f retain];將其reference count加一,這裡的f即是deallocObjcAppDelegate.m內的[first release];,先retain,未來[first release]時,即無法destruct這個pointer所指向的NSString。
(C)問:什麼是autorelease pool? 詳見Objective-C Beginner's Guide的中文的autorelease pool。
答:當創造了一個AutoReleasePool後,@"constant string"會自動進這個pool。stringWithString這種method call也會進pool。只有alloc method 如 [[NSString alloc] initWithString: @"String"] 不使用 auto release pool。
型式:NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[object autorelease]; //並不立刻release,只是記錄reference count減一,直到 [pool release];才算加減總帳。
練習:本段class的練習已作成Xcode可執行的project,共有兩個:
名稱為autoreleaseObjc:demo auto release 影響reference count的情形。
名稱為autoreleasepoolObjc:demo autorelease pool。
(D)問:Foundation Framework是什麼?
答: Foundation Framework包含一堆Classes。Framework裡有物件組(collections)、網路(Networking)、執行緒(Threading)。
(E)問:NSArray?詳見Objective-C Beginner's Guide的中文的NSArray。整個物件詳見SDK 3.0/Xcode/Help/Documentation/iPhone OS 3.0 Library/search for NSArray。
答:有NSArray及NSMutableArray,兩者合稱序列物件組(array collection),Mutable--善變的--表示可以變,NSArray則像是constant。NSMutableArray是NSArray的subClass。
NSArray:
NSCopying,isEqual。
count,objectAtIndex(index從0開始)。
initWithObjects:見下建構型式。return 一個NSArray。
objectEnumerator:回傳一個指向NSEnumerator object的pointer。
NSMutableArray:
NSMutableCopying,
addObjectsFromArray
sortUsingSelector:以下這段語法是說,sort anArrayObject,使用的比較大小方式是以@selector(caseInsensitiveCompare:)所指定的caseInsensitiveCompare這個方法。
語法[anArrayObject sortUsingSelector:@selector(caseInsensitiveCompare:)];
caseInsensitiveCompare:不分英文大小寫的比較方法。
addObject
型式:
建構:[[NSArray alloc] initWithObjects: @"Me", @"Myself", @"I", nil]; // [[NSArray alloc] initWithObjects:Obj1,Obj,....nil];
練習:本段class的練習已作成Xcode可執行的project,名稱為arrayObjc。
練習中用到了:NSEnumerator的nextObject,NSArray中的objectEnumerator、initWithObjects,NSMutableArray的addObject、addObjectsFromArray、sortUsingSelector,@selector。
(F)問:NSDictionary?詳見Objective-C Beginner's Guide的中文的NSDictionary。整個物件詳見SDK 3.0/Xcode/Help/Documentation/iPhone OS 3.0 Library/search for NSDictionary。
答:與NSArray類似,有NSDictionary及NSMutableDictionary兩種,兩者合稱字典(dictionary),Mutable--善變的--表示可以變,NSDictionary則像是constant。NSMutableDictionary是NSDictionary的subClass。這就像一本字典,概念是(key, value),用key來搜尋出所需的value。
NSDictionary:
initWithObjectsAndKeys:
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys: @"one", [NSNumber numberWithInt: 1], @"two",[NSNumber numberWithInt: 3], nil];
-(id) initWithObjectsAndKeys:(id) firstObject, ....
.....
第一個是firstObject的key,接著是secondObject、key,之後即為object、key的配對,直到出現nil為止。
注意:事實上nil一定出現在object的位置。若key是nil,會產生NSInvalidArgumentException。
NSMutableDictionary:
objectForKey:以下的key是由key = [objectOfNSEnumerator nextObject]; 產生的
[[[objectOfNSMutableDictionary objectForKey:key ] description] cString];
setObject: forKey:[mutable setObject:@"Tom" forKey:@"tom@jones.com"];
練習:本段class的練習已作成Xcode可執行的project,名稱為dictionaryObjc。
練習中用到了:NSEnumerator的nextObject,NSDictionary中的keyEnumerator、initWithObjectsAndKeys,NSString中的cString、cStringWithEncoding、NSASCIIStringEncoding。
注意:在dictionaryObjcAppDelegate.m中print function裡,因每個cString都有warning,將第一個cString改為cStringWithEncoding:NSASCIIStringEncoding。
(G)問:NSString?詳見SDK 3.0/Xcode/Help/Documentation/iPhone OS 3.0 Library/search for NSString。
答:曾用過的NSString method如下:
cString:return a C string。
cStringWithEncoding:NSASCIIStringEncoding:retrun a C string,i.e. (char *)。
(H)問:NSEnumerator?詳見SDK 3.0/Xcode/Help/Documentation/iPhone OS 3.0 Library/search for NSEnumerator。
答:曾用過的NSEnumerator method如下:
NSEnumerator *enumerator = [array objectEnumerator];
nextObject:return the next object to be enumberated. e.g. array的一個element.
(I)@property的用法?
答:@property可簡化getter/setter的coding。在@interface內用@property float value;及@ implementation內用"@synthesize value;", 自動由compiler產生 -(float)value; (getter)及-(void)setValue:(float)newValue;(setter)兩method。
Declaration 的型式:
@interface myClass :NSObject {
float value;
}
@property float value;
@end
說明:@property float value;等於下面兩行。
-(float)value;
-(void)setValue:(float)newValue;
Implementation型式:
@interface MyClass:NSObject{
@synthesize value;
}
說明:加上@synthesize value;這一行,compiler會自動synthesize(組合)value及setValue這兩個method,不需要自己動手寫。
複雜declaration型式:
@property (attribute1, attribute2 ... ) type name;
例:@property (getter = getValue, setter = setTheValue ) float value;這個例子是指定getter名為getValue(而非value),setter名為setTheValue(而非setValue)。