LoginSignup
2
2

More than 5 years have passed since last update.

變數和 block/closure 的互動,從 Objective-C 到 Swift

Last updated at Posted at 2015-12-30

Swift 的 closure 即使和 Objective-C 的 block 非常的相像,但是在取得外部變數的值時,做法是不同的。

先看這兩段 code ,做的事情是一樣的:

  1. 宣告一個整數和一個字串
  2. 宣告一個 block
  3. 執行這個 block
  4. 變動整數和字串的值
  5. 再執行這個 block

Objective-C

NSInteger myInt = 1;
NSMutableString *myString = [@"Hello" mutableCopy];

void (^myBlock)(void) = ^() {
    NSLog(@"%@, %@", @(myInt), myString);
};

myBlock();

myInt = 2;
[myString appendString:@", world"];

myBlock();

Swift

var myInt = 1
var myString = "Hello"

let myBlock = {
    print("\(myInt), \(myString)")
}

myBlock()

myInt = 2
myString.appendContentsOf(", world!")


myBlock()

印出結果

可以發現兩個語言在類似語句,呈現結果卻不一樣的結果:

Objective-C

1, Hello
1, Hello, world

說明:

NSInteger 是 primitive type ,變數是存「值」、NSString 是存「記憶體位置」

因此在 myBlock 宣告的時候,各自 capture 這兩個值(1 和 myString 的記憶體位置)
於是在 block 外變更這兩個數值之後再印出,captured 的 1myString 的記憶體位置都不會變動,但是 myString 記憶體位置所存的內容改了,才會印出 Hello, world

Swift

1, Hello
2, Hello, world!

說明:

在 Swift 的 closure 的情形之下, closure 會即時去 capture 執行時變數 當下 的數值。

在執行第一次 myBlock() 的時候,變數值是 1Hello
接著執行第二次前 myBlock() 的時候,變數值就已經被變動成 2Hello, world! ,這兩個值就會被 myBlock() capture 進去用

結語 - 注意使用

知道 Swift 的 data type 基本上都變成 struct 之後,就馬上來嘗試這段 code 的結果會不會不同,於是和預想一樣結果不同了。

兩個很類似的東西即使寫法類似,在不同的語言之下執行的結果會不相同的時候,實作上就可以注意一下執行結果會不會因為特性改變而影響。

參考

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2