Update menu from within RxSwift subscribe

Viewed 239

I am updating a menu (adding, deleting item) from within a RxSwift subscriber. This is how the menu supposed to look like:

enter image description here

The "Item A" will be continuously added and removed, depending on changes of the model, like the following:

// Using ObservableArray (https://github.com/safx/ObservableArray-RxSwift)
model.changeset.rx()
        .observeOn(MainScheduler.instance)
        .subscribe(onNext: { (changes) in

            // Inserts
            for change in changes.insertedElements {
                guard let item = self.newItem(item: change) else { continue }
                let index = (self.view?.indexPlaceholder(at: .specialItem) ?? 0) + 1
                // self.view is a NSMenu Object, so menu item will be added here
                self.view?.insertItem(bridgeItem, at: index)
            }

            // Deletes
            for change in changes.deletedElements {
                guard let menuItems = self.view?.getItems(withIdentifier: .specialItem) else { continue }
                guard let newIndex = menuBridgeObjects.firstIndex(where: {
                    ...
                }
                
                let index = (self.view?.indexPlaceholder(at: .specialItem) ?? 0) + 1 + index
                // self.view is a NSMenu Object, so menu item will be removed here
                self.view?.removeItem(safe: index, onlyIf: .specialItem)
            }

        }).disposed(by: disposeBag)
}

The model.changeset will be populated or altered based on several network activities running in the background.

However, I have realized that while the menu is open, any modifications to the model.changeset and the menu changes through the subscriber, the menu looks like this (missing the separator item below "Item A"):

enter image description here

After closing the menu (tracking lost) and re-open again (no changes on the model this time, so code snippet above will not be triggered), the menu looks as it was supposed to be like this:

enter image description here

I already tried something like NSMenu.update(), but this is somehow not helping to draw the NSMenu properly while open. Do you know if I have overseen something very important here?

1 Answers

The code above will be enabled and triggered immediately after NSMenu's delegate func menuWillOpen(_ menu: NSMenu)

The above feels wrong to me. You should instead setup the code to trigger any time the array changes, don't tie it to menuWillOpen(_:). That way the menu items array will always be in the correct state when the menu opens.

Related