Создать сеттер только в Swift

Когда я создаю сеттер, такой:

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

Это заставило меня сделать добытчик, чего я не хочу делать.

Есть ли способ создать сеттер в Swift без геттера?

Ответы

Ответ 1

Только свойство set не похоже на то, что оно имеет большой смысл. Вероятно, вы должны использовать метод для этого.

Или просто сделайте компилятор счастливым и добавьте получателя, который вы никогда не вызываете:

get {
    return _imageView.frame
}

Ответ 2

В docs:

Геттер используется для чтения значения, а сеттер используется для записи Значение. Предложение setter является необязательным, и когда только геттер необходимо, вы можете опустить оба предложения и просто вернуть запрошенные непосредственно, как описано в "Только для чтения". Но если вы предоставляете предложение setter, вы также должны предоставить getter пункт.

Ответ 3

Ну, если бы мне действительно нужно, я бы использовал это.

Компилятор Swift поддерживает некоторые атрибуты в @available(*, unavailable) получения, поэтому вы можете использовать @available(*, unavailable):

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

Это ясно доставит ваше намерение пользователю кода.

Ответ 4

Чтобы иметь свойство "только для сеттера", вы можете просто иметь простую функцию, которая устанавливает значение; например, если у нас есть частное свойство под названием value, мы можем вызвать вызванный метод setter, configureWithValue(value:String), который обновляет свойство, но не разрешает внешний доступ к свойству:

private var value:String

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

Ответ 5

Вместо этого используйте didSet:

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

Ответ 6

Конечно. Вы можете просто вернуть нуль и сделать тип необязательным:

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

В качестве альтернативы вы можете использовать didSet, чтобы избежать проблемы вместе:

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

Ответ 7

Вы можете вернуть nil из get:

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

Ответ 8

Я нашел одно исключение, где мне действительно нравится переменная setter, которая является, когда я передаю закрытие как единственный параметр в методе с единственной целью сохранить его для последующего выполнения.

Я реализую его как метод следующим образом:

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)
    }
}

Затем я могу вызвать метод следующим образом:

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

Но после закрывающей скобки мне не нравятся тесные парезы, так как у меня может быть много линий в закрытии.

Итак, зная о Trailing Closures, я могу просто изменить код, чтобы выглядеть так:

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

Это прекрасно, и это синтаксис, который Apple показывает для трейлинг-закрытий. Поскольку есть только один параметр и минимализм, что я есть, я испытываю соблазн сделать код еще более компактным и уменьшить его до этого:

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

Это снова показывает, как Apple показывает, что делает Trailing Closures; Кроме того, этот способ обычно используется для какого-то Предиката, где закрытие используется, чтобы сообщить методу, как сделать сортировку, или когда закрытие используется в конце вызова асинхронной функции как закрытие завершения. Я хочу назначить закрытие... Что-то.

Если я заменил метод setColor на переменную, он выглядит так:

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

Теперь вызов выглядит следующим образом:

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

Это знак равенства означает всю разницу. Это показывает, что я назначаю закрытие и не запускаю какую-либо функцию, которая использует закрытие, хотя это и происходит.: ') < - нуждается в смайлике здесь.

Заключительные примечания. Это действительно не имеет ничего общего с закрытием, оно просто показывает, как вы можете сделать только переменную setter, за исключением того, что она все равно возвращает нуль. Он не предназначен для защиты класса от доступа пользователя к переменной для чтения, как только настоящий сеттер. Кроме того, прощайте учебник по трейлинг-закрытию и синглтонам.

Я не могу получить достаточно голосов, чтобы быть правильным ответом, но почему правильный ответ: "Нет, вы не можете! Вы должны использовать вызов метода!". Я говорю "Ni", которому нужен весь этот синтаксис. Просто используйте переменную и не читайте ее, или если вы это сделаете, не возвращайте ее. вроде как ответ Рудольфа Адамковича, который получил 0 голосов.