Внутренние системы GUI вызывают этот метод, и они передают параметр Graphics
в качестве графического контекста, на который вы можете рисовать.
С переменными вы можете использовать двух наблюдателей по умолчанию.
willSet
- представляет момент, когда переменная будет установлена с новым значением
[ 115] - представляет момент, когда переменная была установлена
Также в обозревателе вы можете работать с двумя значениями. С текущей переменной в текущем состоянии и с постоянной зависимой от наблюдателя
struct Struct {
var variable: String {
willSet {
variable // before set
newValue // after set, immutable
}
didSet {
oldValue // before set, immutable
variable // after set
}
}
}
И то же самое вы можете сделать для любого другого сохраненного свойства, так что вы можете использовать его и для структурной переменной в вашем классе [ 1112]
class Class {
var myStruct: Struct? {
didSet {
...
}
}
}
Также вы можете, например, установить в наблюдателе переменную запись уведомления с определенным именем
didSet {
NotificationCenter.default.post(name: Notification.Name("VariableSet"), object: nil)
}
, а затем вы можете добавить определенный класс в качестве наблюдателя для уведомления с этим именем
class Class {
init() {
NotificationCenter.default.addObserver(self, selector: #selector(variableSet), name: Notification.Name("VariableSet"), object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self, name: Notification.Name("VariableSet"), object: nil)
}
@objc func variableSet() {
...
}
}
Попробуйте это, сначала создайте структуру с переменной действия, а когда вы создаете объект структуры, задайте параметр действия для требуемого действия. напр.,
struct testStruct {
var action: (()->())?
var variable: String? {
didSet {
self.action?()
}
}
}
А внутри вашего основного кода - главный класс
var testS = testStruct()
testS.action = {
print("Hello")
}
testS.variable = "Hi"
Когда вы установите testS.variabe = "Hi", он вызовет print ("Hello" )
Стандартные Swift « наблюдатели свойств » (didSet
и willSet
) предназначены для того, чтобы тип мог наблюдать изменения своих собственных свойств, но не для того, чтобы внешние объекты могли добавлять своих собственных наблюдателей. А KVO, который поддерживает внешних наблюдателей, предназначен только для dynamic
и @objc
свойств NSObject
подклассов (как описано в Использование наблюдения значения ключа в Swift ).
Итак, если вы хотите, чтобы внешний объект наблюдал изменения внутри struct
, как уже отмечали другие, вы должны создать свой собственный механизм наблюдения, используя Swift didSet
и тому подобное. Но вместо того, чтобы реализовывать это самостоятельно, свойство за свойством, вы можете написать универсальный тип, чтобы сделать это для вас. Например,
struct Observable<T> {
typealias Observer = String
private var handlers: [Observer: (T) -> Void] = [:]
var value: T {
didSet {
handlers.forEach { [110].value(value) }
}
}
init(_ value: T) {
self.value = value
}
@discardableResult
mutating func observeNext(_ handler: @escaping (T) -> Void) -> Observer {
let key = UUID().uuidString as Observer
handlers[key] = handler
return key
}
mutating func remove(_ key: Observer) {
handlers.removeValue(forKey: key)
}
}
Затем вы можете делать такие вещи, как:
struct Foo {
var i: Observable<Int>
var text: Observable<String>
init(i: Int, text: String) {
self.i = Observable(i)
self.text = Observable(text)
}
}
class MyClass {
var foo: Foo
init() {
foo = Foo(i: 0, text: "foo")
}
}
let object = MyClass()
object.foo.i.observeNext { [weak self] value in // the weak reference is really only needed if you reference self, but if you do, make sure to make it weak to avoid strong reference cycle
print("new value", value)
}
И затем, когда вы обновите свойство, например, как показано ниже, ваше закрытие обработчика наблюдателя будет вызвано: [ 1117]
object.foo.i.value = 42
Стоит отметить, что фреймворки, такие как Bond или RxSwift , предлагают такую функциональность, а также многое другое.