1. 程式人生 > >一個遊戲製作人的自我修養

一個遊戲製作人的自我修養

一,注意事項

1.不可以使用retain,retainCount,release,autorelease 用@select()這樣的呼叫也不行.屬性命名不能以new開頭。

2.若重寫一個類子類的dealloc,不應呼叫[super dealloc],當然也不用寫什麼release釋放一些什麼物件,只是處理一些你覺得必要處理的事情吧,比如中止一個還沒有完成的網路請求.

3.不能使用NSAllocateObjectNSDeallocateObject

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.除了nibTop-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引用的類有

SATSTypesetterNSColorSpaceNSFontNSFontManagerNSFontPanelNSImageNSMenuView,NSParagraphStyleNSSimpleHorizontalTypesetterNSTableCellViewNSTextViewNSViewController,NSWindow, and NSWindowController.

他們的物件,作為屬性,使用assign代替weak;作為變數,使用__unsafe_unretained代替__weak

ARC下也不能weak引用NSHashTableNSMapTable, 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