web-dev-qa-db-ja.com

「致命的なエラー:配列をObjective-Cからブリッジすることはできません」—Swiftを試してみるのはなぜですか。

Swiftプロトコル:

protocol Option {
    var name: String { get }
}

このプロトコルの複数の実装を宣言します—いくつかのクラス、いくつかの列挙型。

次のように宣言されたプロパティを持つView Controllerがあります:

var options: [Option] = []

このプロパティを別のVCのOptionプロトコルでprepareForSegueプロトコルを実装するオブジェクトの配列に設定しようとすると、ランタイムエラーが発生します。

fatal error: array cannot be bridged from Objective-C

なぜこれが機能しないのですか?コンパイラには必要なすべての情報があり、Objective-Cがそれとどう関係するのかまったくわかりません。私のプロジェクトにはSwiftファイルのみが含まれており、これらの配列は提供されていませんNSArrayへのブリッジを必要とするフレームワークメソッドの内外で。

92
Robert Atkins

私は解決策を見つけました。それはかなり... 不満足ですが、動作します。目的のView Controllerで配列を設定する場所:

destinationViewController.options = options.map({$0 as Option})
83
Robert Atkins

コンパイラは、Optionを実装するものの配列を渡すことを知っています

あなたはそこにスリップして、問題の原因を示唆する非常に明快な発言をさせました。 「オプションを実装するものの配列」は、オプションの配列ではありません。

問題は、optionsを作成した時点(prepareForSegue内)のタイプにあります。あなたはそのコードを表示しませんが、その時点であなたがそれをキャスト/タイプすることに失敗することを賭けています。それが割り当てが失敗する理由です。 optionsは実際にOptionを採用することの配列ですが、それだけでは十分ではありません。 Optionの配列としてtypedでなければなりません。

したがって、prepareForSegueに戻り、次のようにoptionsを作成します。

let options : [Option] = // ... whatever ...

現在destinationViewController.optionsに直接割り当てることができます。

簡単なテストケースを次に示します(遊び場で;私は遊び場を嫌いますが、それらを使用することができます):

protocol Option {
    var name : String {get}
}

class ViewController : UIViewController {
    var options : [Option] = []
}

enum Thing : Option {
    var name : String {
        get {
            return "hi"
        }
    }
    case Thing
}

let vc = ViewController()
let options : [Option] = [Thing.Thing]
vc.options = options // no problem

(実際のprepareForSegueを使用して実際のアプリでテストしたところ、正常に動作します。)

22
matt

私は同じ問題を抱えていたので、プロトコルを@objc、あなたの場合は次のようになります

@objc protocol Option {
    var name: String { get }
}

この答え から解決策を得た

16
Juan

これも正常に動作します

destinationViewController.options = options.map{$0}
1
Mykola Denysyuk