ios - View not displaying for childViewController of another ChildViewController -
i'm having issue multi-level hierarchy of childviewcontrollers in ios/swift. there 3 layers current setup lowest-to-highest:
infoviewcontroller
selectionviewcontroller
mainviewcontroller
the infoviewcontroller
has view loaded xib.
selectionviewcontroller
contains uistackview
infoviewcontroller
, uibutton
.
mainviewcontroller
top-level vc embedded in uinavigationcontroller
.
the problem
when add infoviewcontroller
, it's view directly mainviewcontroller
works great.
func setupinfoviewcontrollerdirectlyonmainvc () { addchildviewcontroller(infoviewcontroller) infoviewcontroller.view.embedinside(otherview: infocontainerview) infoviewcontroller.didmove(toparentviewcontroller: self) }
however, if add selectionviewcontroller
mainviewcontroller
using same method, embedded infoviewcontroller
doesn't update it's ui - looks untouched xib file controlling. when not embedded in selectionviewcontroller
behaves expected.
as shown below, ui visible, changes made via asking it's viewcontroller not show - looks xib file created from.
below class setup starting basicinfoview followed 3 viewcontrollers listed above.
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 { /** basicinfoview managed controller. */ var basicinfoview = plbasicinfoview() /** master stack view contains subviews. */ var stackview = uistackview() /** pffile representing image displayed in imageview. setting valid imagefile object automatically laods image server. if set nil, defaultimage displayed instead. */ var imagefile: pffile? { didset { if imagefile != nil { basicinfoview.imagefile = imagefile } else { basicinfoview.photoview.image = defaultimage } } } /** default uiimage displayed in imageview if there no imagefile assigned. */ var defaultimage: uiimage! { return #imageliteral(resourcename: "ios7-camera-outline") } /** main text of infoview */ var titletext:string? { didset { basicinfoview.titlelabel.ishidden = (titletext == nil) basicinfoview.titlelabel.text = titletext } } /** secondary text of infoview. displays under titletext. */ var subtitletext:string? { didset { basicinfoview.subtitlelabel.ishidden = (subtitletext == nil) basicinfoview.subtitlelabel.text = subtitletext } } /** embed our stackview main view. custom embedinsider(otherview:uiview) method (uiview extension) take care of subview additional 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, info view shown , selection button hidden. */ var isassigned = false { didset { selectionbutton.ishidden = isassigned infoview.ishidden = !isassigned } } /** view controller dispaying object in question. */ var infoviewcontroller: plbasicinfoviewcontroller! { return plbasicinfoviewcontroller() } private var infoview: uiview! /** button on bottom of stack. intended allow user assign new value contact property. */ var selectionbutton = plbutton() /** stack view containing 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) } }
some non-relevant code has been removed
notes
please note in practice, both basicinfoviewcontroller , selectionviewcontroller subclassed. example, have contactinfoviewcontroller can passed contact object , display full name, company name , photo (as explained above, works fine). there subclass of selectionviewcontroller complement this: contactselectionviewcontroller. contactselectionviewcontroller has contact object property can assigned , passed embedded contactinfoviewcontroller - point @ data not displayed. have included these subclasses below additional reference.
contactinfoviewcontroller
again, works when placed directly mainviewcontroller.
class plcontactinfoviewcontroller: plbasicinfoviewcontroller { /** contact object managed 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
this vc functions properly, embedded contactinfoviewcontroller not display data. reason, view contactinfoviewcontroller not being updated data when embedded inside controller.
class plcontactassignmentviewcontroller: plselectableinfoviewcontroller { /** contact selected 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 } }
try
var _infoviewcontroller: plbasicinfoviewcontroller? var infoviewcontroller: plbasicinfoviewcontroller! { if let vc = _infoviewcontroller { return vc } _infoviewcontroller = plbasicinfoviewcontroller() return _infoviewcontroller! }
or
lazy var infoviewcontroller: plbasicinfoviewcontroller = { return plbasicinfoviewcontroller() }()
it might because initiating plbasicinfoviewcontroller every time when try access.
wiki
Comments
Post a Comment