I get an unexpected result by using Combine's assign(to:)
directly after compactMap
. Here the code, it's 100% reproducible for me in Xcodes Playground, Xcode Version 13.0 (13A233).
import Combine
import Foundation
class Test {
@Published var current: String?
@Published var latest1: String?
@Published var latest2: String?
@Published var latest3: String?
init() {
// Broken? - compactMap passes nil downstream
self.$current
.compactMap { $0 }
.assign(to: &self.$latest1)
// Fixed by specifying the transform closure type explicitely
self.$current
.compactMap { value -> String? in value }
.assign(to: &self.$latest2)
// Fixed by an additional map inbetween
self.$current
.compactMap { $0 }
.map { $0 }
.assign(to: &self.$latest3)
}
}
let obj = Test()
obj.current = "success"
print("current: \(String(describing: obj.current))")
print("latest1: \(String(describing: obj.latest1))")
print("latest2: \(String(describing: obj.latest2))")
print("latest3: \(String(describing: obj.latest3))")
print("")
obj.current = nil
print("current: \(String(describing: obj.current))")
print("latest1: \(String(describing: obj.latest1))") // nil shouldn't arrive here
print("latest2: \(String(describing: obj.latest2))")
print("latest3: \(String(describing: obj.latest3))")
// Output:
//current: Optional("success")
//latest1: Optional("success")
//latest2: Optional("success")
//latest3: Optional("success")
//
//current: nil
//latest1: nil
//latest2: Optional("success")
//latest3: Optional("success")
Maybe I miss something obvious here? Or could this be a bug in Combine?. Thanks for your attention.
Update: I updated the example code with a more concise version