2017-08-03 77 views
0

以下沿着大書呆子牧場指南書我遇到了一個章節中的一段,要求您創建一個NumberFormatter的實例。一切正常,但我注意到,格式化使用創建closure爲:NumberFormatter只能寫在封閉

class ConversionViewController: UIViewController { 
    let numberFormatter: NumberFormatter = { 
     let nf = NumberFormatter() 

     nf.numberStyle = .decimal 
     nf.minimumFractionDigits = 0 
     nf.maximumFractionDigits = 1 

     return nf 
    }() 

    func updateCelsiusLabel() { 
     if let celsiusValue = celsiusValue { 
      celsiusLabel.text = numberFormatter.string(from: NSNumber(value: celsiusValue.value)) 
     } else { 
      celsiusLabel.text = "???" 
     } 
    } 
} 

只是出於好奇,我試圖像封閉的外創建此格式:

let nf = NumberFormatter() 

nf.numberStyle = .decimal 
nf.minimumFractionDigits = 0 
nf.maximumFractionDigits = 1 

但得到的錯誤說

預計聲明

我的問題是:

  1. 爲什麼不能NumberFormatters封閉外面在這種情況下, 創建?
  2. 括號()表示在 結束時表示什麼?我的猜測是它是自我調用的,但爲什麼它需要成爲?

到目前爲止,我從來沒有見過用這種方式寫封閉。 Apple文檔中是否有解釋這一點的內容?

+0

您可以在創建格式化程序的位置共享更多代碼嗎? –

+0

可能的重複https://stackoverflow.com/questions/29835490/expected-declaration-error-using-swift/29835573#29835573 –

+0

@Ahhhhhhhh我更新了我的問題。讓我知道這是否足夠。 –

回答

1

NumberFormatter以及閉包實例在這裏是一個紅鯡魚:問題是你試圖直接在類型聲明的範圍內更改實例屬性(nf)(儘管你沒有顯示我們所有的代碼確實被包含在類型定義的範圍內),但不在例如一個實例函數或一個初始化器。

比較用:

struct Foo { 
    var a = 1 
    a = 2 // Error: expected declaration 
} 

甲編譯例子是:

struct Foo { 
    var a = 1 
    mutating func mutateMe() { 
     a = 2 // OK 
    } 
} 

至於你質疑2)()用於執行一個僅一次invokation的的括號閉包,其中閉包的返回用於實例化nf。如果您沒有調用它,那麼nf將是() -> NumberFormatter類型的封閉,而不是NumberFormatter的實際實例。比較:

struct Foo { 
    let a: Int = { 
     var a = 1 
     a = 2 
     return a 
    }() // instantiate 'a' of Foo by _once-only 
     // invoking a specified closure_. 
} 

比較相同的概念,而是一個類型聲明/定義之外:

// this is a closure 
let aClosure:() -> Int = { _ in return 42 } 

// this is an invokation of a closure 
// (discarding the result) 
_ = aClosure() 

// this is also an invokation of a closure 
let num = { _ in return 42 }() // 'num' inferred to Int 
+0

我想我現在唯一的問題是在這種情況下類型註釋的概念。 Swift中的變量足夠聰明地確定閉包中的**返回值**是它的值嗎? –

0

nf在這種情況下是一個實例屬性。這本身就是一個擁有自己財產的階級。當你聲明

let nf = NumberFormatter() 

nf是你的,但有默認屬性。你不能在聲明中設置它的屬性。你會得到這個錯誤。

enter image description here

1

第一個答案:我在測試你的遊樂場代碼片段,它並沒有顯示出任何錯誤。我想你可能會做一些與NumberFormatter無關的錯誤。

let nf = NumberFormatter() 
nf.numberStyle = .decimal 
nf.minimumFractionDigits = 0 
nf.maximumFractionDigits = 1 

第二個答案:封閉的結束花括號告訴斯威夫特立即執行關閉。如果省略這些圓括號,則試圖將閉包本身分配給屬性,而不是閉包的返回值。 App Doc

+1

顯然,OP使用一個類。關於問題#1,類和遊樂場的行爲完全不同。 – vadian