아래는 원래 Swift 3 답변이지만 Swift 4는 공정을 단순화하여 주조의 필요성을 없애줍니다.
class Foo: NSObject {
@objc dynamic var bar: Int = 42
}
class ViewController: UIViewController {
let foo = Foo()
var token: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
token = foo.observe(\.bar, options: [.new, .old]) { [weak self] object, change in
if change.oldValue != change.newValue {
self?.edit()
}
}
}
func edit() { ... }
}
참고이 폐쇄 기반의 접근 방식 : 당신이 Int
속성을 관찰하는 경우 예를 들어, foo
개체의 bar
라고
별도의 observeValue
방법을 구현하기 위해 필요의 당신을 가져옵니다을;
context
을 지정하고 해당 컨텍스트를 확인할 필요가 없습니다.
change.newValue
및 change.oldValue
은 올바르게 입력되므로 수동으로 캐스팅 할 필요가 없습니다. 속성이 선택 사항 인 경우 안전하게 포장을 풀어야하지만 캐스팅은 필요하지 않습니다.
확인하십시오 폐쇄 강한 참조주기 ([weak self]
패턴을 따라서 사용)을 소개하지 않습니다하고 있습니다에 대해 당신이 조심해야 할 유일한 것은.
내 원래 Swift 3 답변은 아래와 같습니다.
당신은 말했다 :
이
그러나,이 생각에, 나는이 NSObject
에서 상속하지 않습니다 같은 (I 가정) Int
로 빠른 객체의 기본 요소 일 것이라고 생각하지 않으며, Objective-C 버전과 달리 변경 사전에 배치 될 때 NSNumber
에 박스로 묶이지 않습니다. 당신이 그 값을 보면 관찰 된 속성이 Int
경우
사실, 그것은 NSNumber
로 사전을 통해 올 않습니다. 이 일부 dynamic
재산의 Int
값이 있다면 내가 거라고,
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if let newValue = change?[.newKey] as? NSNumber,
let oldValue = change?[.oldKey] as? NSNumber,
newValue.intValue != oldValue.intValue {
edit()
}
}
을 또는 :
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if let newValue = change?[.newKey] as? NSObject,
let oldValue = change?[.oldKey] as? NSObject,
!newValue.isEqual(oldValue) {
edit()
}
}
또는 사용을 NSNumber
같이
그래서, 당신은 어느 NSObject
세계에 머물 수 일부 빠른 수업에서 나는 앞으로 나아가서 Int
:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if let newValue = change?[.newKey] as? Int, let oldValue = change?[.oldKey] as? Int, newValue != oldValue {
edit()
}
}
당신은 질문 :
는 또한, 보너스 질문은, 어떻게이 of object
변수의 사용을해야합니까? 그것은 내가 이름을 바꾸게하지 않을 것이고, 물론 그들 안에 공백이있는 변수를 좋아하지 않는다. 이 경우, OS가 우리를 위해이를 호출, 그래서 우리는 방법이 외부 라벨 짧은을 사용하지 않습니다
of
는이 메소드를 호출 한 경우 경우에 사용이 매개 변수 (에 대한 외부 레이블입니다 서명). object
은 내부 레이블 (메서드 자체 내에서 사용됨)입니다. Swift는 잠시 동안 매개 변수에 대한 외부 및 내부 라벨 기능을 가지고 있지만 Swift 3의 API에서만 진정으로 받아 들여졌습니다.
이 change
매개 변수를 사용할 때 사용하면 ' 하나 이상의 개체의 속성을 관찰 다시,이 개체는 KVO 예에 다른 처리를 필요로하는 경우 : 다음
foo.addObserver(self, forKeyPath: #keyPath(Foo.bar), options: [.new, .old], context: &observerContext)
baz.addObserver(self, forKeyPath: #keyPath(Foo.qux), options: [.new, .old], context: &observerContext)
그리고 :
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard context == &observerContext else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
if (object as? Foo) == foo {
// handle `foo` related notifications here
}
if (object as? Baz) == baz {
// handle `baz` related notifications here
}
}
제쳐두고, 일반적으로 context
을 사용하는 것이 좋습니다.그 컨텍스트를 사용하여 관찰자를 추가 한 후
private var observerContext = 0
: 그리고하는 private var
을 내 observeValue
수 있도록이 다음
foo.addObserver(self, forKeyPath: #keyPath(Foo.bar), options: [.new, .old], context: &observerContext)
그리고 있는지 수퍼 클래스에 의해 설립의 context
, 그리고 하나 :
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard context == &observerContext else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
if let newValue = change?[.newKey] as? Int, let oldValue = change?[.oldKey] as? Int, newValue != oldValue {
edit()
}
}
흥미 값이 될 수 있지만 아무것도 하나가 '변화'의 모든 값이 NSObject의 것을 실현되면 첫 번째 시도는 실제로 고정 할 수 있습니다 (Int, 즉 String, Date, enum 또는 사용자 정의 클래스 등)가 아닙니다. 그래서 아마도 NSObject 트릭이 작동 할 것입니다. 귀하의 답변에 감사드립니다. – aepryus
그래,'NSObject' 기술은 괜찮습니다. 방금 당신에게 옵션을 보여주고있었습니다. 그건 그렇고, 당신은 Objective-C로 표현할 수있는 타입을 가진 KVO 만 할 수 있습니다 (예를 들어,'enum'을 관찰 할 수 없다; 원시 값으로'enum'을 가져야하고'. rawValue'가 아니라'enum' 그 자체). – Rob
OK,이 포괄적 인 답변에 대해 감사드립니다. – aepryus