一個遊戲製作人的自我修養
一,注意事項
1.不可以使用retain,retainCount,release,autorelease 用@select()這樣的呼叫也不行.屬性命名不能以new開頭。
2.若重寫一個類子類的dealloc,不應呼叫[super dealloc],當然也不用寫什麼release釋放一些什麼物件,只是處理一些你覺得必要處理的事情吧,比如中止一個還沒有完成的網路請求.
3.不能使用NSAllocateObject和NSDeallocateObject
4.你不能在c結構中使用物件,更好的方式是使用Objective-c類來代替.
5.在id和void*之間不能隱士轉換,必須指明相應轉換的生命週期。
6.不能使用NSAutoreleasePool物件,ARC使用@autoreleasepool{}塊代替。
7.不能使用記憶體塊,NSZone已經不需要使用了,現在執行時已經忽略之。
二.基本關鍵字
宣告變數就會預設賦值nil的.
strong// 預設的
相當於retain,在不再使用的時候被釋放
weak
與assign很像,不同在於如果指向的資料被釋放了,那麼這個指向nil
unsafe_unretained
相當於assign,指向的資料如果被釋放,這個指向原來的地址
這些可以定義區域性變數__strong __weak __unsage_unretained
__autor eleasing
標明傳給函式的(id*)型引數是自動釋放的,(函式中(id*)型引數預設的也是這種型別)
1.__autoreleasing不能修飾全域性變數,不能修飾類的屬性.只能再函式塊中用來定義變數,相當與__strong,一旦賦值,直到生命週期結束釋放.
2.對於(id*)型函式引數,預設是__autoreleasing型的,這是由1知道只能傳區域性變數給函式做實參;如果用__weak修飾,那麼會在結束時使的實參為nil,沒有意義;__strong修飾可以用全域性變數,類的屬性值作為引數,其他與__autoreleasing沒有區別
list1
NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", @"aaa"]; NSLog(@"string: %@", string);
列印:(null)
編譯器會給出警告.程式第一句申請了一個記憶體,賦值給string,然後weak引用的string並沒有retain這個記憶體,這個記憶體賦值後在塊內並沒有再次使用,他的週期就存在與賦值語句內部,所以釋放,然後string指向的記憶體被釋放所以他是nil.
list2
@property(nonatomic,strong) NSString* stringA;
@property(nonatomic,weak) NSString* stringB;
- (void)a {
self.stringA = @"string A";
self.stringB = stringA;
self.stringA = nil;
NSLog(@"%@",stringB);
}
-(void)b{
self.stringA = [NSString stringWithFormat:@"%@",@"string A"];
self.stringB = stringA;
self.stringA = nil;
NSLog(@"%@",stringB);
}
- (void)c {
self.stringA = [[NSString alloc] initWithFormat:@"%@",@"string A"];
self.stringB = stringA;
self.stringA = nil;
NSLog(@"%@",stringB);
}
這三個函式分別輸出什麼呢?都是"string A".那麼在函式執行完之後呢?stringB對應的值是什麼?
a:string A// 常字串儲存在靜態儲存區,stringB指向的那個不會被釋放
b:(null)// stringA指向那塊自動釋放的記憶體再塊結束時釋放
c:(null)// stringA就是指向分配字串的記憶體,賦予nil會釋放那塊記憶體
btw:第一次試驗的時候塊內就已經是塊外的值了.囧..
三.Toll-Free Bridging
Core Foundation 物件與Objective-c物件之間的賦值,函式呼叫引數相互轉化時需要用到的關鍵字
__bridge
簡單賦值,不會影響兩邊物件的retain count.
__bridge_transfer
賦值後釋放右邊的物件
__bridge_retained
賦值後也保留不釋放右邊的物件
舉例:
-(void)test { CFStringRef coreFoundationString = CFStringCreateWithCString(CFAllocatorGetDefault(),"C String", kCFStringEncodingUTF8); // 建立 retainCount = 1 id unknownObjectType = (__bridge id)coreFoundationString; // 簡單賦值,不變,retainCount = 1 CFStringRef anotherString = (__bridge_retained CFStringRef)unknownObjectType; // 保留賦值,加一,retainCount = 2 NSString *objCString = (__bridge_transfer NSString *)coreFoundationString; // 釋放賦值,減一,retainCount =1;由於NSString*預設strong,加一,retainCount = 2 NSLog(@"String = %@", objCString); objCString = nil; // 不再指向原記憶體,原記憶體減一,retainCount = 1 CFRelease(anotherString); // 釋放,減一,retainCount = 0}
四.其他
1.開關 :-fobjc-arc 和 -fno-objc-arc 編譯標識來指明單個檔案的方式.
整個工程轉向ARC可以選中工程->選單edit->refactor->convert to Objective-c ARC
2.除了nib的Top-Level(main nib檔案裡面的物件,除了File's owner
和 Application)物件,其他的IBOutlet最好都是weak型的.
3.如果一定要實現類的自定義的retain和release,那麼同時也要在類中加入
-(BOOL)supportsWeakPointers { return NO; }
4.在c型的結構中使用objective-c物件
使用void*代替id;或者使用__unsage_unretained 修飾objective-c物件
5.不能zeroing-weak引用的類有
SATSTypesetter, NSColorSpace, NSFont, NSFontManager, NSFontPanel, NSImage, NSMenuView,NSParagraphStyle, NSSimpleHorizontalTypesetter, NSTableCellView, NSTextView, NSViewController,NSWindow, and NSWindowController.
他們的物件,作為屬性,使用assign代替weak;作為變數,使用__unsafe_unretained代替__weak。
ARC下也不能weak引用NSHashTable, NSMapTable, or NSPointerArray。
6. __block修飾的變數預設也是__strong引用的.
推薦學習:
http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1
http://www.raywenderlich.com/5773/beginning-arc-in-ios-5-tutorial-part-2
參考:
https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/_index.html#//apple_ref/doc/uid/TP40011226
iOS5 programming cook book