在模态 UIViewController 解除后视图生命周期中更新控制器的位置

Where in view lifecycle to update controller after modal UIViewController dismissed

我有一个 UIViewController 和一个需要显示 "lbs" 或 "kg" 的 UILabel。我的应用程序有一个设置屏幕(另一个 UIViewController),它以模态方式显示在第一个视图控制器上,用户可以 select 两个单元中的任何一个并保存他们的偏好。如果单位被更改并且模态设置屏幕被关闭,我当然希望第一个视图控制器上的标签用新的单位值更新(但不刷新整个视图)。我以为我知道如何让它发挥作用,但显然我不知道。

在我的模式设置屏幕上,我有一个 UISegmentedControl 允许用户 select 单位。任何时候更改,此函数都会更新 userDefaults:

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

然后他们可能会关闭设置屏幕。所以,我在我的第一个视图控制器中将其添加到 viewDidLoad

override func viewDidLoad() {
  super.viewDidLoad()

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

那没用,所以我把它移到了 viewWillAppear(),那也没用。我做了一些研究和一些穴居人调试,发现在视图第一次 loaded/presented 之后,这些函数都没有被调用。如果我在由 UINavigationController 管理的 UITableViewController 的层次结构中工作,似乎 viewWillAppear 将被第二次调用,但是当我关闭我的模态 [=] 时不会被调用13=] 以显示其下方的 UIViewController

编辑 1: 这是我正在使用的视图层次结构:

我有点卡在这一点上了,不确定接下来要尝试什么。

编辑 2: 用户可以点击导航栏中的 'Done' 按钮,当他们点击时,dismissSettings() 函数会关闭设置视图:

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)

  }
}

真正的问题

您拼写错误 viewWillAppear。你称它为:

func viewWillAppear()

就 Cocoa Touch 而言,这是一个随机的无关函数,它没有挂钩。你的意思是:

override func viewWillAppear(animated: Bool)

第一个函数的全称是:“viewWillAppear

第二个函数的全称是:“viewWillAppear:animated

一旦你习惯了这一点,Cocoa Touch 使用的极端方法 "overloading" 就会变得更容易。

这在其他语言中非常不同,您可能至少会收到警告。

大家在发题时需要学习的另一课是:Include All Related Code!

有用的日志记录功能,我用它来代替 print 或 NSLog,以帮助找到这些东西:

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

[由于猜测不正确,删除了之前剩余的讨论]