web-dev-qa-db-fra.com

Swift: nil nécessite un type contextuel

J'aimerais réaliser ce qui suit dans le code:

class MyService {

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

    //....

}

Malheureusement, je reçois le message d'erreur "Nil nécessite un type contextuel". Je veux que le sujet soit "vide" jusqu'à ce que j'y mette quelque chose. Comment puis-je passer à zéro comme argument alors? Puis-je le lancer à mon propre type pour le faire fonctionner?

3
breakline

Sur la base de la référence pour RxSwift BehaviorSubject , l'initialiseur init(value:) est déclaré en tant que

public init(value: Element)

Où le paramètre value est décrit comme suit:

value

Valeur initiale envoyée aux observateurs lorsqu'aucune autre valeur n'a été reçue par le sujet encore.

Et où Element est le type d'espace réservé de BehaviorSubject:

public final class BehaviorSubject<Element> ...

Cela signifie que vous devez spécifier le type d'espace réservé Element en tant que type Optional pour pouvoir définir la valeur initiale (utilisée lorsqu'aucune autre valeur n'a été reçue) sur nil. Par exemple.:

class MyService {

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

    //....
}

Vous pouvez également laisser le compilateur déduire l’espace réservé sous la forme MyData? en utilisant le formulaire .none non sucré pour l’argument nil:

class MyService {

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

    //....
}

Pour mieux comprendre le message d'erreur réel, considérons l'exemple autonome suivant:

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?
7
dfri

Bien que la réponse de @ dfri soit techniquement correcte, vous pouvez envisager un type différent lorsque vous travaillez avec RxSwift. Puisque vous voulez que votre sujet soit vide uniquement au début, je suggérerais d'utiliser ReplaySubject ou PublishSubject.

Une question similaire a également été posée sur la page du numéro Github de RxSwift. Autoriser BehaviorSubject sans valeur initiale . Là, kzaher suggère le ReplaySubject.

Votre sujet ressemblerait alors à ceci, sans aucune valeur initiale et sans que MyData soit Optional.

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