ios - Can't get State Restoration to work with Programmatic Navigation Controller -


i'm unable state restoration working navigation controller. using swift , not want use storyboards (programmatic). i've found online either not in swift or using storyboards.

in demo code below, viewcontroller contains simple pickerview, , selection variable keeps track of picker selection. appdelegate presented 2 options. option 1, no navigation controller used , state of picker restored fine, not restored navigation controller in option 2. (in code below, option 1 commented out , option 2 active).

you can copy & paste code below fresh singleview application , should reproduce i've described. (i tested it)

appdelegate code:

import uikit  @uiapplicationmain class appdelegate: uiresponder, uiapplicationdelegate {    var window: uiwindow?    func application(_ application: uiapplication, shouldsaveapplicationstate coder: nscoder) -> bool {     return true   }   func application(_ application: uiapplication, shouldrestoreapplicationstate coder: nscoder) -> bool {     return true   }    func application(_ application: uiapplication, willfinishlaunchingwithoptions launchoptions: [uiapplicationlaunchoptionskey : any]? = nil) -> bool {     window = uiwindow(frame: uiscreen.main.bounds)     window?.makekeyandvisible()     let pickervc = viewcontroller()     //option 1: no navc used     //window?.rootviewcontroller = pickervc      //option 2: navc used     let navc = uinavigationcontroller(rootviewcontroller: pickervc)     navc.restorationidentifier = "pickernav"     window?.rootviewcontroller = navc      return true   }  //  func application(_ application: uiapplication, viewcontrollerwithrestorationidentifierpath identifiercomponents: [any], coder: nscoder) -> uiviewcontroller? { //    let storyboard = uistoryboard(name: "main", bundle: nil) //      if let lastitem = identifiercomponents.last as? string { //        return storyboard.instantiateviewcontroller(withidentifier: lastitem) //      } //    return nil //  } } 

viewcontroller code:

import uikit  class viewcontroller: uiviewcontroller, uipickerviewdelegate, uipickerviewdatasource {    var pickerview: uipickerview!   var selection = 0   let group = ["fruit","vegetable","meat","bread"]    override func viewdidload() {     super.viewdidload()     restorationidentifier = "pickervc"     setuppicker()   }    override func viewdidappear(_ animated: bool) {     super.viewdidappear(animated)     pickerview.selectrow(selection, incomponent: 0, animated: false)   }    override func encoderestorablestate(with coder: nscoder) {     coder.encode(selection, forkey: "selection")     super.encoderestorablestate(with: coder)   }    override func decoderestorablestate(with coder: nscoder) {     selection = coder.decodeinteger(forkey: "selection")     super.decoderestorablestate(with: coder)   }    func setuppicker() {     pickerview = uipickerview()     pickerview.delegate = self     pickerview.datasource = self     view.addsubview(pickerview)      pickerview.translatesautoresizingmaskintoconstraints = false     pickerview.leadinganchor.constraint(equalto: view.layoutmarginsguide.leadinganchor).isactive = true     pickerview.trailinganchor.constraint(equalto: view.layoutmarginsguide.trailinganchor).isactive = true     pickerview.centeryanchor.constraint(equalto: view.centeryanchor).isactive = true     pickerview.heightanchor.constraint(equaltoconstant: 300).isactive = true   }    func numberofcomponents(in pickerview: uipickerview) -> int {     return 1   }    func pickerview(_ pickerview: uipickerview, numberofrowsincomponent component: int) -> int {     return group.count   }    func pickerview(_ pickerview: uipickerview, didselectrow row: int, incomponent component: int) {     selection = pickerview.selectedrow(incomponent: 0)   }    func pickerview(_ pickerview: uipickerview, viewforrow row: int, forcomponent component: int, reusing view: uiview?) -> uiview {     let pickerlabel = uilabel()     pickerlabel.font = uifont.systemfont(ofsize: 26)     pickerlabel.textalignment = .center     pickerlabel.text = group[row]     pickerlabel.textcolor = .white     return pickerlabel   } } 

details of testing: option 1, changing picker followed cmd-shift-h causes selection variable saved in encoderestorablestate. click xcode stop button , run again, , selection variable restored in decoderestorablestate. contrast, option 2 state restoration not work because decoderestorablestate never called selection variable not restored. however, breakpoint @ viewdidappear shows navigationcontroller?.restorationidentifier = "pickernav" , restorationidentifier = "pickervc"

from i've read, suspect may need use viewcontrollerwithrestorationidentifierpath in appdelegate, didn't know how use correctly. attempt @ bottom of appdelegate (the code commented out) causes app crash.

you can add extension viewcontroller , make conform protocol uiviewcontrollerrestoration , implement viewcontrollerwithrestorationidentifierpath method. in viewcontroller's viewdidload function add restorationclass restorationidentifer like

    override func viewdidload() {         super.viewdidload()         restorationidentifier = "pickervc"         restorationclass = viewcontroller.self         setuppicker()     }   extension viewcontroller: uiviewcontrollerrestoration {      static func viewcontroller(withrestorationidentifierpath identifiercomponents: [any], coder: nscoder) -> uiviewcontroller? {         let vc = viewcontroller()         return vc     } 

}

add code in viewcontroller class , delete viewcontrollerwithrestorationidentifierpath method have added in appdelegate


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -