web-dev-qa-db-ja.com

Swift:nilにはコンテキストタイプが必要です

コードで次のことを達成したいと思います。

class MyService {

    let mySubject = BehaviorSubject<MyData>(value: nil)

    //....

}

残念ながら、「nilにはコンテキストタイプが必要です」というエラーが表示されます。実際に何かを入れるまで、その件名は「空」にしておく必要があります。では、引数としてnilを渡すにはどうすればよいですか?自分のタイプにキャストして機能させることはできますか?

4
breakline

RxSwift BehaviorSubjectの参照 に基づいて、init(value:)初期化子は次のように宣言されます

public init(value: Element)

valueパラメータは次のように記述されます。

value

サブジェクトが他の値をまだ受け取っていないときにオブザーバーに送信される初期値。

また、ElementBehaviorSubjectのプレースホルダータイプです。

public final class BehaviorSubject<Element> ...

つまり、(他の値が受信されていないときに使用される)初期値をElementに設定できるようにする場合は、プレースホルダータイプOptionalnilタイプとして指定する必要があります。例えば。:

class MyService {

    let mySubject = BehaviorSubject<MyData?>(value: nil)

    //....
}

または、nil引数に砂糖なしのMyData?形式を使用して、プレースホルダーを.noneとしてコンパイラーに推測させます。

class MyService {

    let mySubject = BehaviorSubject(value: Optional<MyData>.none)

    //....
}

実際のエラーメッセージをよりよく理解するには、次の自己完結型の例を検討してください。

struct Foo<T> {
    init(value: T) {}
}

struct Bar {}

let bar = Bar()

_ = Foo<Bar>(value: bar)           // OK
_ = Foo(value: bar)                // OK, T inferred as Bar
_ = Foo<Bar>(value: nil)           // Error: error: 'nil' requires a contextual type
_ = Foo<Bar?>(value: nil)          // OK
_ = Foo(value: Optional<Bar>.none) // OK, T inferred as Bar?
12
dfri

@dfriの答えは技術的に正しいですが、RxSwiftを使用する場合は別のタイプを検討することをお勧めします。最初は件名を空にしたいので、ReplaySubjectまたはPublishSubjectを使用することをお勧めします。

同様の質問がRxSwiftのGithub問題ページでも行われています。 初期値なしでBehaviorSubjectを許可 。そこで、kzaherがReplaySubjectを提案します。

これで、サブジェクトは次のようになります。初期値はなく、MyDataはOptionalではありません。

let subject = ReplaySubject<MyData>().create(bufferSize: 1)
1
Yannick