Swift:NSUserDefaults 没有立即设置

Posted

技术标签:

【中文标题】Swift:NSUserDefaults 没有立即设置【英文标题】:Swift: NSUserDefaults not setting straight away 【发布时间】:2016-02-29 14:55:35 【问题描述】:

我有什么

我有一个视图控制器 (SelectNameViewController),上面有一个 UITableView 和一个名称列表。当用户点击一个名字时,它会转到一个 ViewController (ResultController),它有一个容器视图,可以加载 3 个 ViewControllers (vc1,vc2, vc3) 允许用户滚动浏览。

ResultController 我有一个连接到 JSON 文件并根据所选名称下载信息的 alamofire 请求:

Alamofire.request(.GET, sendyURLSet, parameters: ["name": passedName, "api_key": api_key])
.responseJSON  response in
    switch response.result 
       case .Success:

       if let value = response.result.value 
          let json = JSON(value)

          self.age = json["age"].stringValue
          self.userInfo.setValue(self.age, forKey: "age")

        
       case .Failure(let error):
           print(error)
   

VC1 我的 viewDidAppear

中有这个
if let a = userInfo.stringForKey("age") 
        print("Age:  \(a)")
     else 
        print("nope")

问题

在从 Alamofire 请求加载内容后,我无法在 PageViewController 子视图上加载数据。

当用户单击一个名称并被带到 ResultController 时,3 个视图会加载到容器视图中。出现的第一个屏幕是 vc1

但是,在控制台中我只是得到:

没有

如果我滑动到 vc2 然后回到 vc1 我会得到:

32 岁

在控制台中。

问题

谁能告诉我为什么 ViewController (vc1) 的第一个演示文稿中没有显示该值并告诉我如何解决它?

快把我逼疯了

【问题讨论】:

不要使用NSUserDefaults在控制器之间传递数据。使用 segues、协议 - 委托模式或通知(按推荐优先级顺序) 三个视图控制器在加载到容器视图时没有转场。 【参考方案1】:

看起来 vc1 的加载速度比数据提取完成的速度快。

要么等待数据加载完毕再加载新的控制器,要么数据完成后直接设置标签

【讨论】:

【参考方案2】:

很可能,对您的Alamofire.request 的回调是在viewDidAppear 之后调用的,这就解释了为什么您看不到您在回调中设置的值。

你应该想要的是你的代码

if let a = userInfo.stringForKey("age") print("Age: \(a)") else print("nope")

在回调执行后调用。

你有几种方法:

resultsController 调用 VC1 以使其更新其 UI;

从回调中加载resultsController(实际上,您确保在回调中第一次调用它的view方法,即当您将其作为子视图添加到父视图时);

或者,您使用KVO 使VC1 观察对userInfo.age 的任何更改。这种方法需要通过从 NSUserDefaults 派生一个新类来自定义 NSUserDefaults

【讨论】:

我认为这与请求有关。我如何从 vc1 等待视图(ReportsView)在加载数据之前完成它的业务? 我对此有点小菜鸟,所以非常感谢您的帮助:) 请看我提到的 3 个选项。 好的,所以对于选项 3 (KVO),我是否相信该选项仅适用于 NSObject 类?所以这行不通,对吧?选项 2: resultsController 中有 alamofire 代码,所以可以重新加载视图吗?这不会造成重复循环吗?这留下了选项 1 - 我不确定如何“调用”视图控制器。有什么指点吗? KVO 实际上可以在 Swift 中工作,没有问题 - 但如果您从未使用过 KVO(在 Swift 或 ObjC 中),那么它无疑是最难的选择。至于选项 2,我知道 resultsController 在某些时候会实例化 VC1 并将其添加为子视图。是对的吗?您应该从回调中运行该代码。至于选项3,只需在resultsController 的属性中保留对VC1 的引用,然后在回调中对该引用调用viewDidAppear(或者更好的是,定义一个临时方法,例如updateUI,那会更干净)【参考方案3】:

尝试以下一个。我想它可能会对你有所帮助。 网络调用完成后(在完成处理程序块中),使用 outlet 为 UI 元素(如标签)设置值。并调用- (void)setNeedsLayout方法。该方法表示图层的子图层的布局发生了变化,必须更新。当图层的边界发生变化时,系统通常会自动调用此方法。

【讨论】:

以上是关于Swift:NSUserDefaults 没有立即设置的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中使用 NSUserDefaults 保存 NSMutableArray 返回 Nil

Swift - 将字典数组保存到 NSUserDefaults

Swift:将 NSDictionary 保存到文件中,因为 NSUserDefaults 会变慢

无法从 NSUserDefaults 检索数据到今天的扩展(Swift)

使用 Swift 将类中的结构保存到 NSUserDefaults

Swift 将图像(截图)保存到 nsuserdefaults