2014-10-08 4 views
15

Когда я создаю сеттер, как например:Создать сеттер только в Swift

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

Его вынуждает меня сделать поглотитель, который я не хочу делать.

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

+2

Неа - звучит, как вы бы лучше с помощью метода. –

+0

Хм, я полагаю, это ОДНА вещь, которую я буду ненавидеть о быстром! – Aggressor

+2

Когда вы используете свойства только для записи? Мне никогда не приходилось это делать. –

ответ

3

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

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

get { 
    return _imageView.frame 
} 
+0

Это мое текущее решение, но мне жаль, что у меня его тоже не было :( – Aggressor

+3

Вы также можете поместить '' '' '' '' '' '' '' '' на кадр imageView, который обновляет scrollView's или использовать AutoLayout с ограничениями, чтобы сделать их равными. –

+0

Setters предназначены для настройки. Наблюдатели свойств предназначены для выполнения задач до/после доступа к ресурсу. Вы должны определенно использовать 'didSet' для того, что вы пытаетесь сделать. – Andrew

12

От docs:

Поглотитель используется для считывания значения, а связующий используется для записи значения. Предложение setter не является обязательным, и если нужен только получатель , вы можете опустить оба предложения и просто вернуть требуемое значение , как описано в «Только для чтения». Но , если вы предоставляете предложение setter, вы также должны предоставить предложение getter .

+21

Там должен быть способ обойти это.Есть МНОГО случаев, я хочу, чтобы сеттеры без геттеров ... – Aggressor

7

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

private var value:String 

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

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

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

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

Было бы хорошо, если бы Swift-компилятор поддерживал некоторые атрибуты на геттерах.

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

Но это не работает в настоящее время: P (Swift 1.2, версия 6.3.1 (6D1002))

Самый быстрый и простой способ будет просить это на Apple, Radar и Apple, Developer Forum.

3

Несомненно. Вы можете просто вернуть ноль и сделать тип дополнительно:

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

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

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

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

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

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

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

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

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

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

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

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

Если я заменю метод SetColor с переменной выглядит следующим образом:

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

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

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

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

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

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

4

Использование didSet вместо:

var masterFrame:CGRect { 
     didSet { 
      _imageView.frame = masterFrame 
      _scrollView.frame = masterFrame 
     } 
    } 
Смежные вопросы