2017-02-21 64 views
1

我試圖讓與RawRepresentable可選參數的通用failable初始化,RawRepresentable初始化基本上這https://www.natashatherobot.com/swift-failable-enums-with-optionals/斯威夫特。可選RawValue

有一對夫婦的方法建議,其中之一就是這個(編輯:第二個條款中的固定let ):

extension RawRepresentable { 

    init?(rawValue optionalRawValue: RawValue?) { 

     guard let rawValue = optionalRawValue, let value = Self(rawValue: rawValue) else { return nil } 

     self = value 
    } 
} 

從這裏https://gist.github.com/okla/e5dd8fbb4e604dabcdc3

我不知道,如果它曾經工作斯威夫特2,但我不能編譯它斯威夫特3.我得到:

Command failed due to signal: Segmentation fault: 11 

有沒有辦法讓它工作?

P.S.我知道文章及其評論的其他方法。

編輯:修復破碎的複製/粘貼的代碼。

+0

編譯器不應該崩潰,所以這顯然是一個錯誤。但它似乎在Swift 3.1中得到了修復(可用於Xcode 8.3 beta)。 – Hamish

+0

[文件錯誤](http://bugs.swift.org)關於崩潰,當然 - 沒有代碼,但是可能會損壞,應該會導致編譯器崩潰。 – rickster

回答

0

我剛剛在Playground中複製並粘貼了您的代碼,我得到的唯一錯誤是它在guard語句中分配value之前缺少let

你確定分段錯誤是因爲這個擴展嗎?

這是對我的作品的代碼(Xcode的8.2.1,3.0.2斯威夫特):

extension RawRepresentable { 

    init?(rawValue optionalRawValue: RawValue?) { 

     guard let rawValue = optionalRawValue, let value = Self(rawValue: rawValue) else { return nil } 

     self = value 
    } 
} 

- 編輯 -

與原始值定義enum後,我確實出現錯誤。

添加這使得遊樂場崩潰:

enum Counter: Int { 
    case one = 1, two, three, four, five 
} 

固定它通過重命名參數init?init?(optRawValue optionalRawValue: RawValue?)。我想問題是你在init?裏面調用Self(rawValue: rawValue),編譯器不知道使用哪一個...

+0

我試圖定義'init?(rawExtValue rawValue:RawValue)'並使用它來執行'let value = Self(rawExtValue:rawValue)'但我仍然得到相同的錯誤。正如我在我的問題中所述,我意識到其他方法,但我想使用'init?(rawValue optionalRawValue:RawValue?)'來工作。或者至少理解編譯器崩潰的原因。 – user1264176

+0

看到這個問題得到更多關於爲什麼編譯器崩潰的細節:http://stackoverflow.com/questions/19014359/how-do-i-view-the-full-build-log-on-xcode5 –

+1

另外,你應該在https://bugs.swift.org提交一個錯誤 –

1

無論編譯這段代碼還是按照你想要的方式工作,我認爲你試圖以錯誤的方式解決潛在的問題。

試圖設計一個這樣的初始化器是一種反模式:Swift中Optionals的設計鼓勵儘早處理和解決可空問題,而不是級聯失敗,以至於很難恢復其起源。如果你有一個返回nil的函數/初始化器,當且僅當它通過nil時,它不應該首先接受nil,並且永遠不會返回nil。

在Swift 3中,您可以爲您的枚舉保留默認的rawValue初始值設定項,並以幾種不同的方式解決原始NatashaTheRobot文章中的問題。

  1. 使用化合物if(或guard)語句。

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
        guard let string = segue.identifier, 
          let identifier = SegueIdentifier(rawValue: string) 
         else { return /* or fatalError or whatever for catching problems */ } 
        switch identifier { 
         // handle all the enum cases here 
        } 
    } 
    
  2. flatMap(兩次)時,執行封閉當且僅當其輸入做它實用的風格是不是nil:

    segue.identifier.flatMap(SegueIdentifier.init).flatMap { identifier in 
        switch identifier { 
         // handle all cases 
        } 
    } 
    

無論哪種方式,你展開期權的兩個級別(segue是否有標識符,以及該字符串是否爲您的SegueIdentifier枚舉的有效原始值)switch之前,這意味着switch必須處理所有有效的SegueIdentifier個案。反過來,這意味着如果您稍後添加一個新的SegueIdentifier箱子,並且不處理它,那麼您會抓住自己。 (相對於switch荷蘭國際集團的東西,可能是一個有效的SegueIdentifier或可能是零,這意味着你需要一個default情況下,這意味着如果有新的SegueIdentifier是你應該被處理,你會默默的失敗。)

+0

好吧,我解析了很多JSON,這意味着檢查每個可能的零值的開銷是巨大的,它只會帶來代碼重複。我認爲我們必須實踐,甚至可以說,每個帶有一個參數的可分解初始化器應該總是接受可選參數。如果他願意,程序員有責任檢查輸入。但我同意,如果它只有在論證是零的情況下才會失敗,那麼它根本不應該失敗。 – user1264176