1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
// RUN: %target-run-simple-swift | %FileCheck %s
// REQUIRES: executable_test
// REQUIRES: objc_interop
import Foundation
struct Guts {
var internalValue = 42
var value: Int {
get {
return internalValue
}
}
}
class Target : NSString {
// This dynamic property is observed by KVO
@objc dynamic var objcValue: String
// This Swift-typed property causes vtable usage on this class.
var swiftValue: Guts
override init() {
self.swiftValue = Guts()
self.objcValue = ""
super.init()
}
required init?(coder aDecoder: NSCoder) {
self.swiftValue = Guts()
self.objcValue = ""
super.init(coder: aDecoder)
}
required init(itemProviderData data: Data, typeIdentifier: String) throws {
fatalError("don't call this initializer")
}
func print() {
Swift.print("swiftValue \(self.swiftValue.value), objcValue \(objcValue)")
}
}
class Observer : NSObject {
var target: Target?
override init() { target = nil; super.init() }
func observeTarget(_ t: Target) {
target = t
target!.addObserver(self, forKeyPath:"objcValue",
options: [.new, .old],
context: nil)
}
override func observeValue(forKeyPath: String?,
of obj: Any?,
change: Dictionary<NSKeyValueChangeKey, Any>?,
context: UnsafeMutableRawPointer?) {
target!.print()
}
}
var t = Target()
var o = Observer()
print("unobserved")
// CHECK: unobserved
t.objcValue = "one"
t.objcValue = "two"
print("registering observer")
// CHECK-NEXT: registering observer
o.observeTarget(t)
print("Now witness the firepower of this fully armed and operational panopticon!")
// CHECK-NEXT: panopticon
t.objcValue = "three"
// CHECK-NEXT: swiftValue 42, objcValue three
t.objcValue = "four"
// CHECK-NEXT: swiftValue 42, objcValue four
//===----------------------------------------------------------------------===//
// Test using a proper global context reference.
//===----------------------------------------------------------------------===//
var kvoContext = Int()
class ObserverKVO : NSObject {
var target: Target?
override init() { target = nil; super.init() }
func observeTarget(_ target: Target) {
self.target = target
self.target!.addObserver(self,
forKeyPath: "objcValue",
options: [.new, .old],
context: &kvoContext)
}
func removeTarget() {
self.target!.removeObserver(self, forKeyPath:"objcValue",
context: &kvoContext)
}
override func observeValue(forKeyPath: String?,
of obj: Any?,
change: Dictionary<NSKeyValueChangeKey, Any>?,
context: UnsafeMutableRawPointer?) {
if context == &kvoContext {
target!.print()
}
}
}
var t2 = Target()
var o2 = ObserverKVO()
print("unobserved 2")
t2.objcValue = "one"
t2.objcValue = "two"
print("registering observer 2")
o2.observeTarget(t2)
print("Now witness the firepower of this fully armed and operational panopticon!")
t2.objcValue = "three"
t2.objcValue = "four"
o2.removeTarget()
print("target removed")
// CHECK: registering observer 2
// CHECK-NEXT: Now witness the firepower of this fully armed and operational panopticon!
// CHECK-NEXT: swiftValue 42, objcValue three
// CHECK-NEXT: swiftValue 42, objcValue four
// CHECK-NEXT: target removed
|