簡體   English   中英

Objective-C區塊

[英]Objective-C blocks

試圖了解blocks如何在objective-c中工作。 閱讀蘋果的文檔時遇到了下一個問題( 鏈接

這是一個示例,說明如何不使用塊:

void dontDoThis() {
    void (^blockArray[3])(void);  // an array of 3 block references

    for (int i = 0; i < 3; ++i) {
        blockArray[i] = ^{ printf("hello, %d\n", i); };
        // WRONG: The block literal scope is the "for" loop.
    }
}

但是我們如何獲得3個不同的塊,分別打印“ hello,0”,“ hello,1”和“ hello,2”? 我嘗試了許多不同的方法,但是每次我都兩次“打招呼”兩次。

塊開始在堆棧上生效,因此,塊的壽命僅與聲明其作用域的范圍一樣長。

for()循環的主體({} s中的循環主體)本身就是一個作用域。 因此,您的代碼會將對堆棧中的某些內容(塊)的引用放入周圍范圍(語言數組)中的變量中。

您需要將塊復制到堆中才能生存:

void dontDoThis() {
    void (^blockArray[3])(void);  // an array of 3 block references

    for (int i = 0; i < 3; ++i) {
        blockArray[i] = [^{ printf("hello, %d\n", i); } copy];
    }
}

如果不使用ARC,則還需要在某個時候-release復制的塊。

您可能會發現這篇博客很方便 (我在Blocks公開后不久寫了它)。 這一部分涉及一些技巧,竅門和陷阱


等等-是的-你是正確的。 ARC編譯器中發生了不可思議的事情,這導致這些塊似乎神奇地出現在堆上。 但是,我在LLVM文檔中找不到任何明確記錄此行為的內容。 如果關閉ARC,您將看到輸出類似於2,2,2,而不是0,1,2。

這是新的行為。 除非有人可以在編譯器中找到明確定義了如何支持此方法的明確注釋,否則我不會依賴於此行為。


@autoreleasepool {
    void (^blockArray[3])(void);  // an array of 3 block references

    for (int i = 0; i < 3; ++i) {
        void (^block)(void) = ^{ printf("hello, %d\n", i); };
        NSLog(@"%p", block);
        blockArray[i] = block;
        NSLog(@"%p", blockArray[i]);
    }

    for (int i = 0; i < 3; ++i) blockArray[i]();
}

輸出:

2012-12-24 16:15:36.752 jkdfjkfdjkdfjk[70708:303] 0x7fff5fbff838
2012-12-24 16:15:36.755 jkdfjkfdjkdfjk[70708:303] 0x100108160
2012-12-24 16:15:36.758 jkdfjkfdjkdfjk[70708:303] 0x7fff5fbff838
2012-12-24 16:15:36.759 jkdfjkfdjkdfjk[70708:303] 0x100108000
2012-12-24 16:15:36.760 jkdfjkfdjkdfjk[70708:303] 0x7fff5fbff838
2012-12-24 16:15:36.760 jkdfjkfdjkdfjk[70708:303] 0x100102e70
hello, 0
hello, 1
hello, 2

因此,該塊在堆棧上創建,並在for()循環范圍之外的分配時自動復制到堆中。

類似的測試還顯示,將塊作為參數傳遞給NSArray的addObject:時,將復制該塊。

如果您真的想 NSMutableArray正常工作,可以使用 NSMutableArray而不是C數組。 NSMutableArray * blocks = [NSMutableArray array];

 
 
 
  
  for (int i = 0; i <= 3; i++) { blocks[i] = ^{ printf("hello %d\\n", i); }; }
 
  

通過將它們添加到 NSMutableArray它們將被從堆棧中復制到堆上,從而使它們的壽命超出了 for循環的范圍。

作為@bbum指出上述不工作,我把這個想法阻止just work與ARC太遠。

您需要主動復制這些塊才能使它們起作用...因此,以下應該起作用

NSMutableArray *blocks = [NSMutableArray array];

for (int i = 0; i <= 3; i++) {
  blocks[i] = [^{ printf("hello %d\n", i); } copy];
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM