首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >视图不显示另一个childViewController的ChildViewController

视图不显示另一个childViewController的ChildViewController
EN

Stack Overflow用户
提问于 2017-08-21 14:13:27
回答 1查看 463关注 0票数 0

我对iOS/Swift中的多层childViewControllers有一个问题。当前设置有三层,从最低到最高:

  1. InfoViewController
  2. SelectionViewController
  3. MainViewController

InfoViewController有一个从XIB加载的视图。

SelectionViewController包含一个带有InfoViewControllerUIButtonUIStackView

MainViewController是顶级VC,通常嵌入到UINavigationController中.

问题

当我将InfoViewController和它的视图直接添加到MainViewController时,一切都很好。

代码语言:javascript
复制
func setupInfoViewControllerDirectlyOnMainVC () {
    addChildViewController(infoViewController)
    infoViewController.view.embedInside(otherView: infoContainerView)
    infoViewController.didMove(toParentViewController: self)
}

但是,如果我使用相同的方法将SelectionViewController添加到MainViewController中,则嵌入InfoViewController不会更新它的UI --它看起来总是像它正在控制的未触及的XIB文件。当它没有嵌入到这个系统中时,SelectionViewController的行为就像预期的那样。

如下图所示,UI是可见的,但是通过询问它的ViewController而对它所做的任何更改都不会出现--它看起来与它创建的XIB文件完全一样。

下面是以BasicInfoView开头的类设置,后面是上面列出的三个viewControllers。

BasicInfoView

代码语言:javascript
复制
class PLBasicInfoView: PLDesignableViewFromXib {

    //
    // MARK: Outlets
    //
    //

    @IBOutlet weak var photoView: PFRoundImageView!
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var subtitleLabel: UILabel!


    var imageFile:PFFile? {
        didSet {
            photoView.file = imageFile
            photoView.loadInBackground()
        }
    }

    //
    // MARK: Initialization
    //
    //

    override var nameOfXib: String {
        return "PLBasicInfoView"
    }

    override var intrinsicContentSize: CGSize {
        return CGSize(width: super.intrinsicContentSize.width, height: 56)
    }

}

BasicInfoViewController

代码语言:javascript
复制
class PLBasicInfoViewController: UIViewController {

    /**
     The BasicInfoView which will be managed by this controller.
     */
    var basicInfoView = PLBasicInfoView()

    /**
     This is the master stack view which contains all subviews.
     */
    var stackView = UIStackView()


    /**
     PFFile representing the image to be displayed in the imageView. Setting a valid imageFile object automatically laods the image from the server. If set to nil, the defaultImage is displayed instead.
     */
    var imageFile: PFFile? {
        didSet {
            if imageFile != nil {
                basicInfoView.imageFile = imageFile
            } else {
                basicInfoView.photoView.image = defaultImage
            }
        }
    }

    /**
     Default UIImage to be displayed in the imageView if there is no imageFile assigned.
     */
    var defaultImage: UIImage! {
        return #imageLiteral(resourceName: "ios7-camera-outline")
    }


    /**
     Main text of the infoView
     */
    var titleText:String? {
        didSet {
            basicInfoView.titleLabel.isHidden = (titleText == nil)
            basicInfoView.titleLabel.text = titleText
        }
    }

    /**
     Secondary text of the infoView. Displays under titleText.
     */
    var subtitleText:String? {
        didSet {
            basicInfoView.subtitleLabel.isHidden = (subtitleText == nil)
            basicInfoView.subtitleLabel.text = subtitleText
        }
    }

    /**
     Embed our stackView into main view. The custom embedInsider(otherView:UIView) method (UIView extension) will take care of the subview additional as well as all layout constraints.
     */
    func setupStackView () {
        stackView.embedInside(otherView: view)
        stackView.axis = .vertical
        stackView.addArrangedSubview(basicInfoView)
    }

    override
    func viewDidLoad() {
        super.viewDidLoad()
        setupStackView()
    }


}

SelectionViewController

代码语言:javascript
复制
class PLSelectableInfoViewController: UIViewController {


    /**
     If true, the info view will be shown and the selection button will be hidden.
     */
    var isAssigned = false {
        didSet {
            selectionButton.isHidden = isAssigned
            infoView.isHidden = !isAssigned
        }
    }


    /**
     The View controller dispaying the object in question.
     */
    var infoViewController: PLBasicInfoViewController! {
        return PLBasicInfoViewController()
    }

    private
    var infoView: UIView!

    /**
     Button on bottom of stack. Intended to allow user to assign a new value to the contact property.
     */
    var selectionButton = PLButton()

    /**
     Stack view containing all subviews.
     */
    var stackView = UIStackView()


    //
    // MARK: UIViewController Overrides
    //
    //

    override
    func viewDidLoad() {
        super.viewDidLoad()
        setupStackView()
        addInfoView()
    }


    private
    func setupStackView () {
        stackView.embedInside(otherView: view)
        stackView.axis = .vertical
    }

    private
    func addInfoView () {
        addChildViewController(infoViewController)
        infoView = infoViewController.view
        stackView.addArrangedSubview(infoView)
        infoViewController.didMove(toParentViewController: self)
    }

}

一些与此无关的代码已被删除。

Notes

请注意,在实践中,BasicInfoViewController和SelectionViewController都是子类。例如,我有一个ContactInfoViewController,它可以传递一个联系人对象并显示全名、公司名称和照片(如上所述,这很好)。还有一个SelectionViewController子类来补充这一点: ContactSelectionViewController。ContactSelectionViewController还有一个Contact对象属性,它可以被赋值,然后传递给嵌入的ContactInfoViewController --这是不显示数据的点。我已将这些子类包括在下面,以供参考。

ContactInfoViewController

同样,当直接放置到MainViewController中时,这是完美的。

代码语言:javascript
复制
class PLContactInfoViewController: PLBasicInfoViewController {

    /**
     Contact object managed by this controller.
     */
    var contact: PLContact? {
        didSet {
            if contact == nil {
                titleText = "Not Set"
                subtitleText = nil
                return
            }
            contact?.fetchIfNeededInBackground(block: { (object, error) in
                if let _ = object as? PLContact {
                    self.updateWithContact()
                }
            })
        }
    }

    override
    var defaultImage: UIImage! {
        return #imageLiteral(resourceName: "ios7-contact-outline")
    }


    private
    func updateWithContact () {
        if let c = contact {
            titleText = c.fullName
            imageFile = c.photo
            c.company?.fetchIfNeededInBackground(block: { (object, error) in
                if let comp = object as? PLCompany {
                    self.subtitleText = comp.name
                } else {
                    self.subtitleText = nil
                }
            })
        }
    }

}

ContactSelectionViewController

此VC功能正常,但嵌入式ContactInfoViewController不显示数据。由于某些原因,ContactInfoViewController的视图在此控制器内嵌入时不会使用数据进行更新。

代码语言:javascript
复制
class PLContactAssignmentViewController: PLSelectableInfoViewController {


    /**
     The contact currently selected by this contorller
     */
    var selectedContact: PLContact? {
        didSet {
            isAssigned = !(selectedContact == nil)
            contactInfoViewController.contact = selectedContact
        }
    }


    override
    var infoViewController: PLBasicInfoViewController! {
        return PLContactInfoViewController()
    }


    private
    var contactInfoViewController: PLContactInfoViewController {
        return infoViewController as! PLContactInfoViewController
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-21 16:07:35

试一试

代码语言:javascript
复制
    var _infoViewController: PLBasicInfoViewController?
    var infoViewController: PLBasicInfoViewController! {
        if let vc = _infoViewController {
            return vc
        }
        _infoViewController = PLBasicInfoViewController()
        return _infoViewController!
    }

代码语言:javascript
复制
lazy var infoViewController: PLBasicInfoViewController = {
        return PLBasicInfoViewController()
    }()

这可能是因为每次尝试访问时都要启动PLBasicInfoViewController。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45799307

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档