iOS/SwiftのchildViewControllerのマルチレベル階層に問題があります。別のChildViewControllerのchildViewControllerの表示を表示しない
InfoViewController
SelectionViewController
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ファイルとまったく同じように見えます。以下
上記の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
}
}
私は質問から多くを伝えることはできませんが、私はXcodeののビューのデバッグは、この種の問題、特に制約調査のための便利な機能を発見しました。 (あなたがそれを試していない場合には) –
@PhillipMillsそれはレイアウトの問題よりも参照する問題のほうが多いようです。すべてが正しく表示されます。ただし、InfoViewがInfoViewControllerにアタッチされたInfoViewと同じインスタンスではないように動作しています。 –
申し訳ありません。私は「それはいつも触れられていないXIBのように見える」と誤解しました。 –