简体   繁体   中英

Swift: NSUserDefaults not setting straight away

What I have

I have a view controller ( SelectNameViewController ) with a UITableView on with a list of names. When the user clicks a name, it goes to a ViewController ( ResultController ) which has a container view that loads 3 ViewControllers ( vc1 , vc2 , vc3 ) allowing the user to scroll through.

On ResultController I have an alamofire request that connects to a JSON file and downloads information based on the name selected:

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

On VC1 I have this in my viewDidAppear

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

Problem

I am having trouble loading data on a PageViewController child view after the content has been loaded from an Alamofire request.

When the user clicks a name and is taken to the ResultController the 3 views load into the container view. The first screen to appear is vc1 .

However, in the console I just get:

Nope

If I swipe to vc2 and then back to vc1 I get:

Age 32

in the console.

Question

Can someone tell me why the value is not showing up on the first presentation of the ViewController ( vc1 ) and tell me how to fix it?

It is driving me crazy

Likely, the callback to your Alamofire.request is called after viewDidAppear , and that explains why you do not see the value you set in the callback.

What you should want is that your code

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

is called after the callback is executed.

You have several means to this:

  • resultsController calls into VC1 to make it update its UI;

  • load resultsController from the callback (actually, you make sure you call its view method for the first time in the callback, ie, when you add it as a subview to the parent);

  • or, you use KVO to make VC1 observe any changes to userInfo.age . This approach requires customising NSUserDefaults by way of deriving a new class from it.

looks like vc1 is being loaded quicker than the data fetch is completing.

Either wait for the data to be loaded before you load the new controllers, or set the label directly when the data has completed

Try following one. I think it may help you.

On completion of your network call (in completion handler block) set values to UI elements like label, using outlets. And call - (void)setNeedsLayout method.

This method to indicate that the layout of a layer's sublayers has changed and must be updated. The system typically calls this method automatically when the layer's bounds change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM