FlexLayout icon indicating copy to clipboard operation
FlexLayout copied to clipboard

When I used FlexLayout to set constraints for a UITableViewCell, I removed the dataSource of a UITableView and then refreshed the UITableView, which caused a crash. The version of FlexLayout is 2.0.10, and I wonder if this issue is related to YogaKit.

Open cirelir opened this issue 5 months ago • 4 comments

I have obtained the following error log.

terminating due to uncaught exception of type std::logic_error: Cannot set measure function: Nodes with measure functions cannot have children.

cirelir avatar Sep 24 '25 02:09 cirelir

Could you share a reproducible project or code?

heoblitz avatar Sep 24 '25 11:09 heoblitz

I fixed it. The reason was that I called markdirty after dynamically adding a view to a container.

But I think it's difficult to locate and resolve the issue this way. Could it be more specific?

Finally, I just commented out ”flex.markDirty()” and that worked.

 self.insuranceContainer.subviews.forEach({$0.removeFromSuperview()})
        self.insuranceContainer.flex.define { flex in
            details.forEach { info in
                let label = YYLabel().then {
                    $0.numberOfLines = 0
                    $0.font = 12.design.font()
                    $0.lineHeight = 18.design
                }
                label.setText(info)
                
                flex.addItem().direction(.row).justifyContent(.start).alignItems(.start).define { flex in
                    flex.addItem(UIImageView(image: UIImage(named: "icons_16pt_insurance_checked"))).size(CGSize(width: 16.design, height: 16.design)).marginTop(1.design)
                    flex.addItem(label).grow(1)
                }
            }
        }
        
       // self.insuranceContainer.flex.markDirty()

cirelir avatar Sep 24 '25 13:09 cirelir

class TestView: UIView {
  override init(frame: CGRect) {
    super.init(frame: .zero)

    self.flex.addItem(UIView())
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
      self.subviews.forEach {
        $0.removeFromSuperview()
      }
      self.flex.markDirty()
    }
  }
}

In the code above, while YogaKit's markDirty handling is possible, it seems that an error occurs in Yoga setMeasureFunc because the child nodes are not empty.

I think the YogaKit logic needs to be changed to be a bit more safe.

heoblitz avatar Sep 25 '25 01:09 heoblitz

The current options are to either

remove the container’s flex markDirty, or

call flex.layout() when the view changes dynamically (which updates the Node tree based on the current UIView hierarchy).

self.subviews.forEach {
  $0.removeFromSuperview()
}
self.flex.layout()
self.flex.markDirty()

heoblitz avatar Sep 25 '25 01:09 heoblitz