Combine .assign not working as intended?

I'm trying to test out using combine with the UIScreen notifications, but the way I'm using .assign doesn't seem to working.


First, I defined a variable that stores whether a secondary display is available or not. I also added a debug print using didSet so I could check to see if the value was being changed.


class SceneDelegate: UIResponder, UIWindowSceneDelegate {    
    var secondaryDisplayAvailable = false {
        didSet {
            print("◆◆◆ secondaryDisplayAvailable did change to: \(secondaryDisplayAvailable)")
        }
    }


The following code compiles, but the value in secondaryDisplayAvailable does not get updated.


let _ = NotificationCenter.default.publisher(for: UIScreen.didConnectNotification)
    .map( {_ in return true} )
    .assign(to: \SceneDelegate.secondaryDisplayAvailable, on: self)


Assuming that my keypath is correct, when an additional screen is connected the value in secondaryDisplayAvailable should be updated.


If I change the code to update the variable using a keypath in .sink the value will get updated.


let _ = NotificationCenter.default.publisher(for: UIScreen.didConnectNotification)
     .map( {_ in return true} )
     .sink { (available) in
         self[keyPath: \.secondaryDisplayAvailable] = available
     }


Am I missing something about .assign or is this a bug?

Replies

Try adding receive(on:):


let _ = NotificationCenter.default.publisher(for: UIScreen.didConnectNotification) 
    .map( {_ in return true} ) 
    .receive(on: RunLoop.main)
    .assign(to: \SceneDelegate.secondaryDisplayAvailable, on: self) 


It worked for me