2016-04-04 54 views
3

在Swift的捕獲列表語法中似乎出現了一個奇怪的語法小故障。如果我聲明多個變量捕獲,捕獲符只適用於第一個:爲什麼捕獲說明符在捕獲列表中是可選的?

let closure = { [unowned x, y] in … } 

現在我希望yunowned,但它似乎並沒有這樣的情況:

class Test { 

    var callback: (Void -> Void)? 

    init() { 
     print("init") 
    } 

    deinit { 
     print("deinit") 
    } 
} 

func makeScope() { 
    let x = Test() 
    let y = Test() 
    y.callback = { [unowned x, y] in 
     print(y) 
    } 
} 

makeScope() 
print("done") 

此打印:

init 
init 
deinit 
done 

所以y似乎強烈地捕獲並創建一個保留週期,防止物體被交易位於。是這樣嗎?如果是的話,允許列表中的「空」捕獲說明符是否有意義?還是有沒有原因[unowned x, y]不被視爲[unowned x, unowned y]

回答

8

...允許列表中的「空」捕獲說明符有意義嗎?

是的。 捕獲符(「弱」,「無主」及其變體),只能與引用類型使用,但也有要捕捉值類型案件 (這裏是一個例子: Pass value to closure? )。

您也可能想要強烈地捕獲引用類型。 捕獲引用類型確保參考(指針) 本身是由值捕獲,如在下面的例子表明:

class MyClass { 
    let value : String 
    init(value : String) { 
     self.value = value 
    } 
} 

var ref = MyClass(value: "A") 

let clo1:() -> Void = { print(ref.value) } 
let clo2:() -> Void = { [ref] in print(ref.value) } 

ref = MyClass(value: "B") 

clo1() // Output: B 
clo2() // Output: A 

當執行第一封閉,ref閉合 內是對一個參考創建爲MyClass(value: "B")的對象。

第二封閉捕獲的ref在創建 閉合的時間的值,並且當新的值 被分配給var ref這不會改變。

+0

很好,趕快,謝謝。你認爲編譯器在引用類型前缺少說明符時至少會產生警告嗎? – zoul

+0

@zoul:不,請看上面的例子。 –

+0

太好了,謝謝!我認爲讓我不高興的是,'無主x,y'這個簡單常見的例子看起來有誤導性(參見圖1)。'用類C語言編寫的int a,b'),而使用臨時變量可以很容易地(更明確地)解決無說明符引用類型捕獲的罕見情況。 – zoul

1

按照syntax EBNF,這種治療unowned捕捉符是完全故意的:

關閉簽名→參數子句功能結果選擇in­
關閉簽名→標識符表函數結果 opt­in­
閉合簽名→捕獲列表參數子句功能結果選擇in­
閉合簽名→捕獲列表標識符列表函數結果選擇­in
閉合簽名→捕獲列表in­
捕獲列表→[捕獲一覽項目]
捕獲 - 列表項→捕獲列表項捕獲列表項捕獲列表項
捕獲列表項→捕捉符選擇表達
捕捉符→weak | unowned | unowned(safe) | unowned(unsafe)­

三線在底部定義<capture-list-items><capture-list-item><capture-specifier>製作最相關的。

<capture-list-items>生產是逗號分隔的列表<capture-list-item>,與capture-specifier連接到每個單獨的<capture-list-item>,不<capture-list-items>列表作爲一個整體。

這非常有道理,因爲它可以讓程序員完全控制捕獲單個參數。當說明符適用於整個列表時,替代方案將取消這種靈活性。

爲什麼要在捕獲列表中包含標識符而不修改其捕獲說明符?

看來Swift的設計師的哲學是在任何可能的時候提供智能的默認行爲。在大多數情況下,Swift可以找出一種方法來捕獲基於表達類型的最有意義的表達式,而不需要程序員的參與。當編譯器沒有足夠的信息來找出基於上下文捕獲變量的正確方法時,將會出現明確的捕獲說明符。

+0

那麼,問題是爲什麼要在捕獲列表中包含標識符而不修改其捕獲說明符?但正如馬丁所說,這實際上對於價值類型有意義。但是,引用類型的行爲是一個等待發生的錯誤,恕我直言。 – zoul

0

爲了回答您的具體問題:

爲什麼捕捉符中捕獲列出了可選?

因爲默認行爲是捕獲任何必要的變量(強烈捕獲引用類型)。默認情況下,如果要使用它們的值,則不需要在捕獲列表中明確指定它們。 (但如果你正在捕獲selfself.property排位賽將是必要的。)

...有[unowned x, y]不作爲[unowned x, unowned y]治療的原因是什麼?

出於同樣的原因:默認是強烈捕獲。 unowned不適用於捕獲列表中的其他項目;這不僅僅是語法現在的作用。

相關問題