2015-11-28 2 views
2

Comment implémenter une liaison de données bidirectionnelle avec Swift 2.0?Comment implémenter la liaison bidirectionnelle avec Swift?

Supposons que j'ai la classe modèle suivant (en utilisant lite Couchbase):

@objc(Person) 
class Person: NSObject{ 
    @NSManaged var firstName: NSString? 
    @NSManaged var lastName: NSString? 
} 

Et j'aime lier les propriétés à un formItemDescriptor donné comme ceci:

class FormItemDescriptor { 
    var tag: String? 
    var value: Any? 
} 

Comment pourrais-je lier la propriété FormItemDescriptor.value à la propriété Person.firstName en utilisant la liaison bidirectionnelle?

Donc les changements dans le modèle apparaissent dans le formulaire et vice versa?

Répondre

5

Swift ne prend pas en charge les liaisons hors de la boîte, mais vous pouvez les réaliser avec des structures telles que ReactiveKit. Par exemple, lorsque vous déclarez une propriété observable, vous pouvez la lier à une autre propriété observable.

let numberA: Property<Int> 
let numberB: Property<Int> 

numberA.bindTo(numberB) 

Pour faire bi-directionnel, bind dans d'autres sens aussi:

numberB.bindTo(numberA) 

Maintenant, chaque fois que vous changez l'un d'eux, l'autre va changer.

Votre exemple est un peu plus difficile, car vous devez effectuer des liaisons à partir de propriétés @NSManaged qui ne peuvent pas être créées Observable. Ce n'est pas impossible, mais pour travailler les propriétés de la personne devraient soutenir l'observation de la valeur-clé (KVO).

Par exemple, étant donné un objet Person et une étiquette, vous pouvez prendre une propriété de la propriété compatible KVO avec la méthode rValueForKeyPath et se lient alors que observable à l'étiquette, comme ceci:

let person: Person 
let nameLabel: UILabel 

person.rValueForKeyPath("firstName").bindTo(nameLabel) 

Si vous avoir un objet intermédiaire comme votre FormItemDescriptor, alors vous devrez rendre ses propriétés observables.

class FormItemDescriptor { 
    var tag: Property<String?> 
    var value: Property<Any?> 
} 

Maintenant, vous pouvez établir des obligations

let person: Person 
let descriptor: FormItemDescriptor 

person.rValueForKeyPath("firstName").bindTo(descriptor.value) 

Parce que firstName n'est pas observable, vous ne pouvez pas faire de liaison dans une autre direction de sorte que vous devrez mettre à jour manuellement chaque fois que value changements.

descriptor.value.observeNext { value in 
    person.firstName = value as? NSString 
} 

Nous avons également jeté à ne NSString parce value est de type Any?. Vous devriez repenser cela et voir si vous pouvez le rendre plus fort.

Notez que les liaisons UIKit proviennent du framework ReactiveUIKit. Consultez notre documentation de ReactiveKit pour plus d'informations.

+0

Merci beaucoup pour l'explication détaillée! Je pensais à faire les deux manières contraignantes - 'a.bindTo (b), b.bindTo (a)' - mais avait peur des boucles sans fin ou tout autre comportement étrange. Donc, c'est vraiment économiser pour faire une liaison bidirectionnelle de ce genre en utilisant ReactiveKit? –

+1

Oui, il est parfaitement sûr - il existe un mécanisme interne qui rend les boucles sans fin impossible. –