0

I have made a custom UIViewController called ViewControllerA and want to be able to use it so I made a UIViewControllerRepresentable called ViewControllerARepresentable as shown below, the problem though is that when I call ViewControllerARepresentable in my SwiftUI view and pass a value for stringToUpdateTextView, the ViewControllerA says the htmlTextView(UITextView) in ViewControllerA is nil and I'm not sure why.

ViewControllerARepresentable(stringToUpdateTextView: "<html>Send some Html Text as string here</html>")

ViewControllerARepresentable

public struct ViewControllerARepresentable: UIViewControllerRepresentable {
  var stringToUpdateTextView: String

  public func makeUIViewController(context: Context) -> ViewControllerA {
    let viewcontrollerA = ViewControllerA(testString: testingString)

    return viewcontrollerA
  }

  public func updateUIViewController(_ uiViewController: ViewControllerA, context: Context) {}
}

ViewControllerA

open class ViewControllerA: UIViewController {

  public var stringToUpdateTextView: String

  override open func viewDidLoad() {
    super.viewDidLoad()

htmlTextView.text = stringToUpdateTextView
  }

  @IBOutlet weak var htmlTextView: UITextView!

  public init(testString: String) {
    self.testString = testString
    super.init(nibName: nil, bundle: nil)
  }

  required public init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

Crash occurs at htmlTextView.text = stringToUpdateTextView saying that htmlTextView.text is nil even though its an IBOutlet. Any Change made to the htmlTextView like background color ,etc, also causes a crash if called in viewDidAppear or viewDidLoad

Di Nerd Apps
  • 770
  • 8
  • 15

1 Answers1

5

When instantiating your view controller in makeUIViewController, the outlets haven't been initialised yet.

The following code loads your view controller from the storyboard, and updates the properties in updateUIViewController:

ViewController.swift

import UIKit
import SwiftUI

class ViewController: UIViewController {

  @IBOutlet weak var htmlTextView: UITextView!

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
  }

}

struct ViewControllerWrapper: UIViewControllerRepresentable {
  typealias UIViewControllerType = ViewController

  @Binding var text: String

  func makeUIViewController(context: Context) -> ViewController {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    guard let viewController =  storyboard.instantiateViewController(
      identifier: "ViewController") as? ViewController else {
        fatalError("Cannot load from storyboard")
    }
    return viewController
  }

  func updateUIViewController(_ uiViewController: ViewController, context: Context) {
    uiViewController.htmlTextView.text = text
  }

}


struct ViewControllerPreview: PreviewProvider {
  static var previews: some View {
    ViewControllerWrapper(text: .constant("hello world!"))
  }
}

SwiftUIView.swift

struct SwiftUIView: View {
  @State var text = "Text"
  var body: some View {
    HStack {
      TextField("Text:", text: $text)
      ViewControllerWrapper(text: $text)
    }
  }
}
Peter Friese
  • 6,709
  • 31
  • 43
  • what if i wanted to add a small uitableview with buttons(1-3) under the uitextview? would i have to use coordinators in the UIViewControllerRepresentable? – Di Nerd Apps Jun 17 '20 at 10:20
  • Can you explain what you're trying to achieve? I.e. how the entire screen should look like? It might be helpful to create a drawing / sketch and add this to your question. – Peter Friese Jun 17 '20 at 10:29
  • i want to have a large uitextview first with converted html text (done) and then a tableview underneath the uitextview i tried adding a ZStack around the UIViewControllerRepresentable and putting a List {} below it but this is difficult to position – Di Nerd Apps Jun 17 '20 at 10:45
  • Have you considered using a `UIViewRepresentable` instead? Might make positioning of the `UITextView` easier. – Peter Friese Jun 17 '20 at 11:12
  • great idea im trying thsat right now, and then just do a regular SwiftUI list below it? – Di Nerd Apps Jun 17 '20 at 11:24
  • Exactly. In SwiftUI it's easy to compose UIs like that. – Peter Friese Jun 17 '20 at 11:30
  • 1
    thanks so much this works perfectly! BIG UP much respect from Jamaica! – Di Nerd Apps Jun 17 '20 at 11:34
  • Great, I'm glad it worked out :-) It might be interesting to see the final code, so feel free to post this as an answer to your own question. – Peter Friese Jun 17 '20 at 11:35