Keeping strong references with dynamic subviews in Swift

北战南征 提交于 2021-01-29 15:27:39

问题


I'm trying to implement a dynamic view composed UI elements sent by the backend, meaning it is not known beforehand how many and which UI elements will be displayed, the server sends JSON containing the types of fields that need to be rendered.

So for example the sever sends:

  • type: paragraph
  • type: textfield

Then I instantiate a class I have for each of those elements and add their views as subviews to my main dynamic view:

class DynamicViewController: UIViewController {
    // array of subviews, textfield is one element in this array (-> textfield not editable)
    var subViews: [UIView] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        
        getFields(completion: { result in
            for (index, element) in result!.form.enumerated() {
                let initializedClass = element.getClass()
                self.subViews.append(initializedClass.view)
                self.addChild(initializedClass)
                self.view.addSubview(self.subViews[index])
                initializedClass.didMove(toParent: self)
            }
        })
    }
}

The problem I am getting with the "textfield" element, is that the textfield doesn't seem to be editable, tapping on it does nothing. However, when I change the code to assign the initializedClass.view to a specific variable, it does work:

class DynamicViewController: UIViewController {
    // variable specifically for the textfield's view (-> textfield is editable)
    var textfieldView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        getFields(completion: { result in
            for (index, element) in result!.form.enumerated() {
                if (index == 0) {
                    let initializedClass = element.getClass()
                    let initializedView = initializedClass.view
                    self.textfieldView = initializedClass.view
                    self.addChild(initializedClass)
                    self.view.addSubview(initializedView!)
                }
            }
        })
    }
}

This second implementation works then (the picker does open), which I got from UIPickerView delegate not called in a subview.

My question is why this is happening and how I can make this work without having to declare static variables for each element, but rather work with an array or some collection that keep references to the elements.

The TextField:

class CustomTextField: UIViewController {
    private let labelElement = UILabel(frame: CGRect(x: 20, y: 150, width: 350, height: 20))
    private let textfieldElement = UITextField(frame: CGRect(x: 20, y: 200, width: 350, height: 40))
    
    init(label: String) {
        self.labelElement.text = label
        textfieldElement.borderStyle = UITextField.BorderStyle.roundedRect
        
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(labelElement)
        view.addSubview(textfieldElement)
    }
}

回答1:


From your code it looks like getClass() will return a subclass of UIViewController (I can see this because you are calling addChild). You also have to call initializedClass.didMove(toParent: self) sometimes after addChild otherwise the embedding of the VC is not completed and could cause issues. I am not entirely sure this is the cause of your problem but I suggest to try it. Also when implementing a container VC you need to take care of AutoLayout for the children's view, where are you managing the constraints? If you don't add any constraint the view of the VC you are adding as child will have the same size of the main UIWindow. You actually could also get rid of var subViews: [UIView] = [] and just rely on children array from UIViewController. It will contain all the VCs you add when calling addChild.



来源:https://stackoverflow.com/questions/65882928/keeping-strong-references-with-dynamic-subviews-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!