Jim Jim - 3 months ago 23
Swift Question

Where in view lifecycle to update controller after modal UIViewController dismissed

I have a

UIViewController
with a
UILabel
that needs to display either "lbs" or "kg". My app has a settings screen (another
UIViewController
) that is presented modally over the first view controller and the user can select either of the two units and save their preference. If the units are changed and the modal settings screen is dismissed, I of course want the label on the first view controller to be updated with the new units value (but without refreshing the whole view). I thought I knew how to make it work, but evidently I don't.

On my modal settings screen, I have a
UISegmentedControl
to allow the user to select units. Anytime it's changed, this function updates
userDefaults
:

func saveUnitsSelection() {
if unitsControl.selectedSegmentIndex == 0 {
UserDefaultsManager.sharedInstance.preferredUnits = Units.pounds.rawValue
} else {
UserDefaultsManager.sharedInstance.preferredUnits = Units.kilograms.rawValue
}
}


Then they would likely dismiss the settings screen. So, I added this to
viewDidLoad
in my first view controller:

override func viewDidLoad() {
super.viewDidLoad()

let preferredUnits = UserDefaultsManager.sharedInstance.preferredUnits
units.text = preferredUnits
}


That didn't work, so I moved it to
viewWillAppear()
and that didn't work either. I did some research and some caveman debugging and found out that neither of those functions is called after the view has been loaded/presented the first time. It seems that
viewWillAppear
will be called a second time if I'm working within a hierarchy of
UITableViewController
s managed by a
UINavigationController
, but isn't called when I dismiss my modal
UIViewController
to reveal the
UIViewController
underneath it.

Edit 1:
Here's the view hierarchy I'm working with:
enter image description here

I'm kinda stuck at this point and not sure what to try next.

Edit 2:
The user can tap a 'Done' button in the navigation bar and when they do, the
dismissSettings()
function dismisses the Settings view:

class SettingsViewController: UITableViewController {

let preferredUnits = UserDefaultsManager.sharedInstance.preferredUnits
// some other variables set here

override func viewDidLoad() {
super.viewDidLoad()

self.navigationController?.navigationBar.topItem?.title = "Settings"

navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(self.dismissSettings(_:)))

if preferredUnits == Units.pounds.rawValue {
unitsControl.selectedSegmentIndex = 0
} else {
unitsControl.selectedSegmentIndex = 1
}
}

func dismissSettings(sender: AnyObject?) {
navigationController?.dismissViewControllerAnimated(true, completion: nil)

}
}

Answer

THE REAL PROBLEM

You misspelled viewWillAppear. You called it:

func viewWillAppear()

As far as Cocoa Touch is concerned, this is a random irrelevant function that hooks into nothing. You meant:

override func viewWillAppear(animated: Bool)

The full name of the first function is: "viewWillAppear"

The full name of the second function is: "viewWillAppear:animated"

Once you get used to this, the extreme method "overloading" that Cocoa Touch uses gets easier.

This is very different in other languages where you might at least get a warning.

The other lesson that everyone needs to learn when posting a question is: Include All Related Code!

Useful logging function I use instead of print or NSLog, to help find these things:

class Util {
    static func log(message: String, sourceAbsolutePath: String = #file, line: Int = #line, function: String = #function, category: String = "General") {
        let threadType = NSThread.currentThread().isMainThread ? "main" : "other"
        let baseName = (NSURL(fileURLWithPath: sourceAbsolutePath).lastPathComponent! as NSString).stringByDeletingPathExtension ?? "UNKNOWN_FILE"
        print("\(NSDate()) \(threadType) \(baseName) \(function)[\(line)]: \(message)")
    }
}

[Remaining previous discussion removed as it was incorrect guesses]

Comments