Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI UIViewControllerRepresentable.updateUIViewController not being called after updating @State

Tags:

ios

swift

swiftui

I'm trying to alter a UIViewControllerRepresentable's @State and noticing updateUIViewController(_ uiViewController:context:) is not being called after I do.

I'm having trouble knowing if this is a bug or something I'm doing wrong.

For example:

struct ContentView: UIViewControllerRepresentable {
  @State var blah: Int = 0

  func makeUIViewController(context: UIViewControllerRepresentableContext<ContentView>) -> UIViewController {
    let vc = UIViewController()
    let button = UIButton(frame: CGRect(x: 40, y: 40, width: 100, height: 100))
    button.setTitle("Next", for: .normal)
    button.addTarget(context.coordinator, action: #selector(context.coordinator.nextPressed), for: .primaryActionTriggered)
    vc.view.addSubview(button)
    return vc
  }

  func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<ContentView>) {
    // Not being called when `blah` is updated.
    var random = SystemRandomNumberGenerator()
    let red = CGFloat(Double(random.next() % 255) / 255.0)
    let blue = CGFloat(Double(random.next() % 255) / 255.0)
    let green = CGFloat(Double(random.next() % 255) / 255.0)
    uiViewController.view.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1)
  }


  func makeCoordinator() -> ContentView.Coordinator {
    return Coordinator(self)
  }


  final class Coordinator {
    var contentView: ContentView
    init(_ contentView: ContentView) {
      self.contentView = contentView
    }

    @objc func nextPressed() {
      // This is getting called.
      contentView.blah += 1
    }
  }
}

I would expect to see the viewController's background change however I don't see updateUIViewController being called at all when blah is updated.

I have also tried passing in a binding and using @ObservableObject.

Thanks!

like image 575
dostrander Avatar asked Oct 29 '19 11:10

dostrander


1 Answers

You have to bind at least one value to make update work as only binding can make the UIViewController join the notification chain.

If the @state is used, it will be a local notice and cannot trigger the update.

Now you can @Binding var blah: Int to see the big change.

like image 113
E.Coms Avatar answered Oct 20 '22 22:10

E.Coms