-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Open
Labels
Description
Previous ID | SR-6066 |
Radar | rdar://problem/39297127 |
Original Reporter | @bobergj |
Type | Bug |
Status | Reopened |
Resolution |
Attachment: Download
Environment
Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)
Additional Detail from JIRA
Votes | 1 |
Component/s | Foundation |
Labels | Bug |
Assignee | None |
Priority | Medium |
md5: 71e8a3bdae50c0f3c476808e7f3096c9
Issue Description:
Test case:
import Foundation
print("Check what the print output of a double optional is..")
let optionalString: Optional<String> = nil
let optionalOptionalString: Optional<Optional<String>> = optionalString
print(optionalOptionalString)
print("OK, now to the actual test")
class A : NSObject {
@objc dynamic var anOptionalString: String? = nil
}
func testObserve() {
let a = A()
let keyPath = \A.anOptionalString
a.observe(keyPath, options: [.old, .new]) { (objectChanged, observedChange) in
print("oldValue: \(observedChange.oldValue)")
print("newValue: \(observedChange.newValue)")
}
a.anOptionalString = nil
a.anOptionalString = "abc"
a.anOptionalString = "def"
}
testObserve()
Output:
Check what the print output of a double optional is..
Optional(nil)
OK, now to the actual test
oldValue: nil
newValue: nil
oldValue: nil
newValue: Optional(Optional("abc"))
oldValue: Optional(Optional("abc"))
newValue: Optional(Optional("def"))
Expected output:
Check what the print output of a double optional is..
Optional(nil)
OK, now to the actual test
oldValue: Optional(nil)
newValue: Optional(nil)
oldValue: Optional(nil)
newValue: Optional(Optional("abc"))
oldValue: Optional(Optional("abc"))
newValue: Optional(Optional("def"))
In https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/NSObject.swift
public struct NSKeyValueObservedChange<Value> {
///newValue and oldValue will only be non-nil if .new/.old is passed to `observe()`. In general, get the most up to date value by accessing it directly on the observed object instead.
public let newValue: Value?
public let oldValue: Value?
...
}
Since we are passing the options:
[.old, .new]
above, the expectation is that newValue and oldValue aren't nil.
I got bit by this when using observe in a generic context and using a guard statement to bind newValue and oldValue in the beginning of the observe callback closure.