0

iOS/SwiftのchildViewControllerのマルチレベル階層に問題があります。別のChildViewControllerのchildViewControllerの表示を表示しない

  1. InfoViewController
  2. SelectionViewController
  3. MainViewController

InfoViewControllerはXIBからロードされたビューを持っている:最低ツー最高から現在の設定には3つの層があります。

SelectionViewControllerは、InfoViewControllerおよびUIButtonを有するUIStackViewを含む。

MainViewControllerは、通常UINavigationControllerに埋め込まれているトップレベルのVCです。

問題

私はInfoViewControllerを追加し、MainViewControllerすべてが素晴らしい作品にそれが直接ビューです。それは常に、それが制御している手つかずのXIBファイルのように見える - 私はMainViewControllerからSelectionViewControllerは、同じ方法を使用して追加した場合

func setupInfoViewControllerDirectlyOnMainVC() { 
    addChildViewController(infoViewController) 
    infoViewController.view.embedInside(otherView: infoContainerView) 
    infoViewController.didMove(toParentViewController: self) 
} 

しかし、組み込みInfoViewControllerは、それがUIだ更新されません。それがの場合、SelectionViewControllerに埋め込まれたは予期したとおりに動作します。

以下に示すように、UIは表示されますが、ViewControllerを確認して変更を加えても表示されません。作成されたXIBファイルとまったく同じように見えます。以下

example of empty UI

上記の3つviewControllers続いBasicInfoView始まるクラス設定です。

BasicInfoView

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

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

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) 
    } 

} 

いくつかの非関連のコードが

ノート

を削除されている実際には、BasicInfoViewControllerとSelectionViewControllerの両方をサブクラス化していることに注意してください。たとえば、Contactオブジェクトを渡してフルネーム、会社名、写真を表示できるContactInfoViewControllerがあります(上で説明したとおりです)。これを補うSelectionViewControllerのサブクラスもあります:ContactSelectionViewController。 ContactSelectionViewControllerにはContactオブジェクトプロパティもあり、これを割り当てて埋め込みContactInfoViewControllerに渡します。これはデータが表示されないポイントです。私は、これらのサブクラスをさらに参照するために以下に含めました。

ContactInfoViewController

MainViewControllerに直接入れたときに再度、これは完璧に動作します。

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からのビューが、このコントローラの内部に埋め込まれているときに、データで更新されていません。

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 
    } 

} 
+0

私は質問から多くを伝えることはできませんが、私はXcodeののビューのデバッグは、この種の問題、特に制約調査のための便利な機能を発見しました。 (あなたがそれを試していない場合には) –

+0

@PhillipMillsそれはレイアウトの問題よりも参照する問題のほうが多いようです。すべてが正しく表示されます。ただし、InfoViewがInfoViewControllerにアタッチされたInfoViewと同じインスタンスではないように動作しています。 –

+0

申し訳ありません。私は「それはいつも触れられていないXIBのように見える」と誤解しました。 –

答えて

1

あなたはPLBasicInfoViewControllerあなたがアクセスしようとするたびに開始されているので、それはあるかもしれない

var _infoViewController: PLBasicInfoViewController? 
    var infoViewController: PLBasicInfoViewController! { 
     if let vc = _infoViewController { 
      return vc 
     } 
     _infoViewController = PLBasicInfoViewController() 
     return _infoViewController! 
    } 

または

lazy var infoViewController: PLBasicInfoViewController = { 
     return PLBasicInfoViewController() 
    }() 

を試してみてください。

関連する問題