「致命的なエラー:アレイをObjective-Cからブリッジできません」—Swiftを試してみたのはなぜですか?


92

私はSwiftプロトコルを宣言しました:

protocol Option {
    var name: String { get }
}

このプロトコルの複数の実装(一部のクラス、一部の列挙型)を宣言します。

次のように宣言されたプロパティを持つビューコントローラーがあります。

var options: [Option] = []

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

fatal error: array cannot be bridged from Objective-C

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


6
@objcプロトコルに付加しようとしましたか?stackoverflow.com/a/28029568/377369
Fabio Poloni

1
プロトコルの実装のいずれかが列挙型の場合、これは機能しません:「非クラスタイプ 'Foo'はクラスプロトコル 'Option'に適合できません」
Robert Atkins

なぜそれがクラスプロトコルでなければならないのですか?私はそれをObj-Cフレームワークや、Swift ArrayがNSArrayにブリッジされることを必要とするその他のものに渡していません。
Robert Atkins、

彼らがSwiftとObjective-Cを連携させる方法は、依然として私には秘密です。私はただ「働く」または「働かない」多くのことを「受け入れる」必要があります。
Fabio Poloni、2015年

9
なぜこれはそれほど多くの反対票を持っているのですか?私には公正で明確な質問のように見えます。
Guven、2015

回答:


83

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

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

配列全体をキャストできませんか?options as [Option]
Kostiantyn Koval

いいえ。試してみましたが(Xcode 6.3.1(6D1002))、動作しません。どのような場合でもキャストする必要ありません。コンパイラーは、Optionを実装するものの配列を渡すことを知っています。
Robert Atkins

2
「オプションを実装するものの配列」ああ、しかしそれは必要なオプションの配列と同じではありません。私の答えを見てください。
マット

1
これは機能し、はい、それは非常に不満足です...これは必要ありません。Swiftはhtisを処理できるはずです。
オスカーゴメス

私は同意します...それはこのように機能しますが、それは非常に満足のいくコードではありません
Michael

22

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

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

問題は、optionsそれを作成した時点での背中のタイプにあります(でprepareForSegue)。あなたはそのコードを示していませんが、その時点でそれをキャスト/タイプできないことに私は賭けています。そのため、割り当ては失敗します。optionsOptionを実際に採用する一連のことかもしれませんが、それだけでは十分ではありません。Optionの配列として入力する必要があります。

したがって、に戻って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ので実際のアプリでこれをテストしましたが、正常に動作します。)


1
コンパイラ実行時にThingがオプションであることを認識しいるため、これは極端に壊れていると思います。とにかく、以下の私の独自の回答へのコメントで述べたように、キャスト(viewController.options = things as [Option])も、[Option]ここで提案するように明示的に型指定された一時変数の作成も実際には機能しません。どちらの場合も、実行時エラーが発生します。
Robert Atkins、2015年

次に、それがなぜ私にとって有効なのかを説明する必要があります。あなたが述べていない何か他のことが起こっています。あなたがもっと多くのコードを明らかにしないなら、私はあなたが本質的な何かを控えていると単に疑わなければなりません。
マット

多分。しかし、これが最初にObjective-Cと何が関係しているのか(元のランタイムエラーに対して)はまだ混乱しています。 NSArray。
Robert Atkins

2
このように見てください。機能するコードを示しました。あなたはしているではない私のコード示さない仕事を-私は与えられたデータから、あなたの問題を再現することはできません。再現してください。
マット

1
@ CristiBăluțăこれは、「この問題はまだ修正されていない」と主張する前に知っておく必要があることです
matt

16

私は同じ問題を抱えていたので、プロトコルをでマークすることで修正し@objcました。あなたの場合は次のようになります

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

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


1
元の質問のコメントのように、プロトコルの実装者のいずれかがSwift Enumsである場合、これは機能しません。私の場合はどちらでしょう。
Robert Atkins

typo obcjはobjcである必要があります
Alan Scarpa

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.