web-dev-qa-db-fra.com

Créer un poseur uniquement dans Swift

Quand je crée un setter comme celui-ci:

   var masterFrame:CGRect{
        set{
            _imageView.frame = newValue
            _scrollView.frame = newValue
        }
    }

Cela m'oblige à faire un getter, ce que je ne veux pas faire.

Existe-t-il un moyen de créer un setter dans Swift sans getter?

32
Aggressor

Une propriété set only ne semble pas avoir beaucoup de sens. Vous devriez probablement utiliser une méthode pour cela à la place.

Ou, faites simplement plaisir au compilateur et ajoutez un getter que vous n'appelez jamais:

get {
    return _imageView.frame
}
6
Dave Wood

De la docs :

Le getter est utilisé pour lire la valeur et le setter est utilisé pour écrire la valeur. La clause setter est facultative et lorsque seul un getter est nécessaire, vous pouvez omettre les deux clauses et renvoyer simplement la valeur demandée directement, comme décrit dans Propriétés calculées en lecture seule. Mais si vous fournissez une clause setter, vous devez également fournir une clause getter.

13
David

Eh bien, si je le dois vraiment, je l'utiliserais.

Le compilateur Swift prend en charge certains attributs sur les getters, vous pouvez donc utiliser @available(*, unavailable):

public subscript(index: Int) -> T {
    @available(*, unavailable)
    get {
        fatalError("You cannot read from this object.")
    }
    set(v) {
    }
}

Cela livrera clairement votre intention à l'utilisateur du code.

12
Eonil

Utilisez plutôt didSet:

var masterFrame:CGRect {
        didSet {
            _imageView.frame = masterFrame
            _scrollView.frame = masterFrame
        }
    }
8
Matjan

Pour avoir une "propriété setter-only", vous pouvez simplement avoir une fonction simple qui définit la valeur; par exemple, si nous avons une propriété privée appelée value, nous pouvons avoir une méthode de définition appelée, configureWithValue(value:String) qui met à jour la propriété mais ne permet pas l'accès extérieur à la propriété:

private var value:String

func configureWithValue(value:String) {
  self.value = value
}
8
Zorayr

Sûr. Vous pouvez simplement retourner un nil et rendre le type facultatif:

var color: MyColorEnum? {
    get { return nil }
    set {
      switch newValue! {
      case .Blue:
        view.backgroundColor = UIColor.blueColor()
      case .Red:
        view.backgroundColor = UIColor.redColor()
      }
    }
  }

Alternativement, vous pouvez utiliser didSet pour éviter le problème tous ensemble:

var color: MyColorEnum! {
  didSet {
    switch color {
      case .Blue:
        view.backgroundColor = UIColor.blueColor()
      case .Red:
        view.backgroundColor = UIColor.redColor()
      }
  }
}
6
seo

Vous pouvez renvoyer nil depuis get:

var input: CGRect? {
    set(value) {
        guard let value = value else { return }
        // process the value here
    }
    get {
        return nil
    }
}
2
Rudolf Adamkovič

vous pouvez donner un modificateur d'accès à set pour propriété et sur didSet vous pouvez l'affecter à _imageView.frame & _scrollView.frame

private(set) var masterFrame:CGRect {
            didSet{
                _imageView.frame = masterFrame
                _scrollView.frame = masterFrame
            }
        }
0
Same7Farouk

J'ai trouvé une exception où j'aime vraiment une seule variable setter, c'est quand je passe une fermeture comme seul paramètre dans une méthode dans le seul but de l'enregistrer pour une exécution ultérieure.

Je l'implémente comme une méthode comme suit:

typealias ThemeSetter = () -> ()

class Theme {

    fileprivate var themeSetters:[ThemeSetter] = []

    class var shared: Theme {
        struct Singleton {
            static let instance = Theme()
        }
        return Singleton.instance
    }
        ...

    func setColor(_ entry:@escaping ThemeSetter) {
        entry()
        themeSetters.append(entry)
    }
}

Je peux alors appeler la méthode comme suit:

    Theme.shared.setColor({
        self.navigationBar.barTintColor = Theme.shared.gameBarTint
    })

Mais je n'aime pas les paréthèses fermées après la parenthèse fermée, car j'ai peut-être plusieurs lignes dans la fermeture.

Donc, en connaissant les fermetures arrière, je peux simplement changer le code pour qu'il ressemble à ceci:

    Theme.shared.setColor() {
        self.navigationBar.barTintColor = Theme.shared.gameBarTint
    }

C'est tout à fait correct et c'est la syntaxe que Apple montre pour les fermetures de fin. Comme il n'y a qu'un seul paramètre et étant le minimaliste que je suis, je suis tenté de rendre le code encore plus léger et de le réduire) pour ça:

    Theme.shared.setColor {
        self.navigationBar.barTintColor = Theme.shared.gameBarTint
    }

Encore une fois, comment Apple montre comment faire des fermetures de fin; sauf que cette façon est généralement utilisée pour une sorte de prédicat où la fermeture est utilisée pour indiquer à la méthode comment faire un tri ou quand la fermeture est utilisé à la fin d'un appel de fonction asynchrone comme clôture de fin. Ce que je veux, c'est assigner la fermeture à ... Quelque chose.

Si je remplace la méthode de setColor par une variable, cela ressemble à ceci:

    var setColor:ThemeSetter? {
        didSet {
            if setColor != nil {
                setColor?()
                themeSetters.append(setColor!)
                setColor = nil
            }
        }
    }

Maintenant, l'appel ressemble à ceci:

    Theme.shared.setColor = {
        self.navigationBar.barTintColor = Theme.shared.gameBarTint
    }

Ce signe égal signifie que toute la différence est. Cela montre que j'assigne une fermeture et que je n'exécute aucune fonction qui utilise la fermeture, même si c'est le cas. : ') <- besoin d'émoticônes ici.

Notes finales: Cela n'a vraiment rien à voir avec les fermetures, cela montre simplement comment vous pouvez créer une variable setter uniquement, sauf que cela renvoie toujours un zéro. Il n'est pas destiné à protéger la classe contre le fait que l'utilisateur accède à la variable pour la lecture comme le ferait un vrai setter. Pardonnez également le didacticiel sur les fermetures arrière et les singletons.

Je n'ai peut-être pas assez de votes positifs pour être la bonne réponse, mais pourquoi la bonne réponse est-elle: "Non, vous ne pouvez pas! Vous devez utiliser un appel de méthode!". Je dis "Ni" à cela, qui a besoin de toute cette syntaxe. Utilisez simplement une variable et ne la relisez pas ou si vous le faites, ne la retournez rien. un peu comme la réponse de Rudolf Adamkovic, qui a obtenu 0 Up Votes.

0
Sojourner9