web-dev-qa-db-ja.com

Xcode 9.3(Swift 4.1)のコード化可能な「イニシャライザーはありません」

Xcode 9.3(Swift 4.1を使用)に更新した後、次の問題が見つかりました。

  1. 空のプロジェクトを作成し、新しい.Swiftファイルを追加して、2つの新しいクラスを作成します。

    Created to Codable classes

    class CodableOne: Codable {
    
        let some: String
    
    }
    
    class CodableTwo: Codable {
    
        var some: String
    
    }
    

    ビルドは成功します

  2. タイプCodableOneCodableTwoに新しい定数を追加します。

    Added a new constant to CodableOne

    class CodableOne: Codable {
    
        let some: String
        let another: CodableTwo
    
    }
    
    class CodableTwo: Codable {
    
        var some: String
    
    }
    

    ビルドは成功します

  3. クラスCodableTwoを別のファイルに移動します(たとえば、ViewController.Swift)

    CodableTwo moved to another file

    ビルドは失敗します

これでエラーが発生しますが、これは消えません。 Codableクラスは、初期化子を必要とするべきではありません(前のステップで示したように)。

この背後にある問題とその解決方法に関するアイデアは大歓迎です!


追伸Xcode 9.2には問題はありません。プロジェクト/ビルドパスのクリーニングも、Xcode 9.3の再インストールも役立ちません。

37
EBDOKUM

コメントに記載 のように、私は2つのことをしなければなりませんでした:

  1. Compilation ModeからWhole Moduleの内部プロジェクト設定/ビルド設定

    Compilation Mode set to Whole Module

  2. プロジェクト設定/ビルドフェーズ/ソースのコンパイルの下でファイルを並べ替えます。具体的には、エラーが発生したファイルをリストの先頭に移動しました。

    ヒント:ファイルの名前を検索し、結果が複数ある場合、ファイルをその小さいリストの一番上にドラッグしても、そのファイルが前面に表示されます。

24
Tamás Sengel

これは、Swift 4.1コンパイラのバグです。この問題を回避するには、4kmanの回答に記載されている手順を実行するか、宣言のletを単にvarに変更します。

class C1 : Decodable { 
  let str: String 
  // error: Class 'C1' has no initializers - if class C's `c1` is a let constant. 
}

class C : Decodable {
  var c1: C1 // << Change to `var`, compilation succeeds.
}

回避策 りんごの礼儀Swiftエンジニア

これもthe4kmansの回答も役に立たない場合は、コンパイルしないモデルに別のinitを追加できます。クラスに大量の変数がある場合は、initをクラッシュさせてコンパイラを満足させます。 Codable初期化子は引き続き合成されます。

class C1: Decodable {
    let str: String

    @available(*, deprecated, message: "Do not use.")
    private init() {
        fatalError("Swift 4.1") 
    }
}
21
Oscar Apeland

すべてのクラスが同じファイルにあるにもかかわらずこの問題が発生しましたが、より深いクラスに構造体を使用するとうまくいくようです

0
Hogdotmac