Texture icon indicating copy to clipboard operation
Texture copied to clipboard

`Re-render Clipping Corners when User Interface Style Changes` is broken

Open Kaelzs opened this issue 4 years ago • 0 comments

I found a pr here Re-render Clipping Corners when User Interface Style Changes to fit the new iOS 13 dark mode, and I found a bug.

here's the minimum re-produce path.

view.backgroundColor = theDynamicColor0

// We set the corner radius first
// So, the clipping corner (layer) should be generated now.
someNode.backgroundColor = theDynamicColor0
someNode.cornerRadius = 10
someNode.cornerRoundingType = .clipping
someNode.frame = CGRect(x: 100, y: 100, width: 100, height: 100)

// Then, the trait collection changed
// And the node ignore it, because the node hasn't been loaded yet.
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    self.overrideUserInterfaceStyle = .dark
    self.someNode.setPrimitiveTraitCollection(ASPrimitiveTraitCollectionFromUITraitCollection(self.traitCollection))
}

// And we add the node | view (maybe in tableNode)
// The node display the outdated corner.
DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
    self.view.addSubview(self.someNode.view)
}

So when we set cornerRadius or maskedCorners when cornerRoundingType is ASCornerRoundingTypeClipping, the node will re-render the clipping layer in main thread immediately, and it will never synced with the backgroundColor changed. When the global traitCollection did change, the node's asyncTraitCollectionDidChangeWithPreviousTraitCollection callback will judge if node is loaded

if (primitiveTraitCollection.userInterfaceStyle != previousTraitCollection.userInterfaceStyle) {
    if (loaded) {
        ... // re-render the clipping layer
    }
}    

And if the node is not loaded yet (maybe in tableNode, but not in UI hierarchy), it will not change the layer's appearance, and when we display the node, the corner broke.

Kaelzs avatar Dec 06 '21 14:12 Kaelzs