Search code examples
iosjsonswiftnetwork-programmingalamofire

Change label with Alamofire


I want to put the information I get from the API into the corresponding Label inside, I use the Alamofire to get the API information and put the corresponding Label inside, but I found that my Label text has not been changed, would like to ask this happen What's the problem? Who can answer me for me? Thank you

Here is my Information class:

import Foundation
import Alamofire
class Information {
    var account:String?
    var date:String?
    var name:String?
    var sex:String?
    var born:String?
    var phoneNumber:String?
    var email:String?

    init(account:String,date:String,name:String,sex:String,born:String,phoneNumber:String,email:String) {
        self.account = account
        self.date = date
        self.name = name
        self.sex = sex
        self.born = born
        self.phoneNumber = phoneNumber
        self.email = email
    }

    typealias DownlaodComplete = () -> ()



    func downlaodInformation(completion:@escaping DownlaodComplete) {
        Alamofire.request("http://163.18.22.78:81/api/Information/A1001a").responseJSON { response in
             print(response)
            if let json = response.result.value as? Dictionary<String,Any> {
                guard let account = json["Account"] as? String ,let date = json["Date"] as? String , let name = json["Name"] as? String , let sex = json["Sex"] as? String , let born = json["Born"] as? String , let phoneNumber = json["PhoneNumber"] as? String , let email = json["Email"] as? String   else {
                    return
                }
                self.account = account
                self.date = date
                self.name = name
                self.sex = sex
                self.born = born
                self.phoneNumber = phoneNumber
                self.email = email
                completion()
            }

        }
    }

}

And here is my ViewController:

   var information:Information?

    override func viewDidLoad() {
        super.viewDidLoad()
        if let currentInformation = information {
            currentInformation.downlaodInformation {
                self.accountLabel.text = currentInformation.account
                self.dateLabel.text = currentInformation.date
                self.nameLabel.text = currentInformation.name
                self.sexLabel.text = currentInformation.sex
                self.bornLabel.text = currentInformation.born
                self.phoneNumberLabel.text = currentInformation.phoneNumber
                self.emailLabel.text = currentInformation.email

            }
        }

Solution

  • Here you declare information to be an Information optional

    var information:Information?
    

    But you don't give it an initial value, meaning that it is nil

    In your viewDidLoad you do the right thing and check whether information has a value:

    if let currentInformation = information
    

    But I'm guessing it hasn't, because you haven't created an instance of it. Therefore you don't end up inside your if let loop and never calls downlaodInformation

    So you need to create a new instance of Information before you can use it.

    However

    This leads to a problem with your Information class.

    If I was to instantiate an Information object, I'd need to have:

    • account
    • date
    • name
    • sex
    • born
    • phoneNumber
    • email

    Or..since you've created them as optionals, pass nil.

    But that is not what you want, is it?

    I'm guessing you'd like to do something along the lines of this in your ViewController:

    let information = Information()
    

    and then in viewDidLoad

    information.downloadInformation( currrentInformation in 
        self.accountLabel.text = currentInformation.account
        ....
    }
    

    To do so you could change your Information to not take parameters to its constructor and then create another struct which would hold your data.

    Something like:

    struct Information {
        var account:String?
        var date:String?
        var name:String?
        var sex:String?
        var born:String?
        var phoneNumber:String?
        var email:String?
    }
    
    class InformationLoader {
        func downloadInformation(completion: (Information?) -> ()) {
            Alamofire.request("http://163.18.22.78:81/api/Information/A1001a").responseJSON{ response in
            print(response)
            if let json = response.result.value as? Dictionary<String,Any> {
                guard let account = json["Account"] as? String,
                let date = json["Date"] as? String, 
                let name = json["Name"] as? String, 
                let sex = json["Sex"] as? String, 
                let born = json["Born"] as? String, 
                let phoneNumber = json["PhoneNumber"] as? String, 
                let email = json["Email"] as? String else {
                   completion(nil)
                   return
                }
                let information = Information(account: account, date: date, name: name, sex: sex, born: born, phoneNumber: phoneNumber, email: email)
                completion(information)
            }
        }
    }
    

    And you'd need to change your code in the ViewController to:

    let informationLoader:InformationLoader()
    

    In viewDidLoad

    informationLoader.downloadInformation{ currentInformation in
        if let currentInformation = currentInformation {
            //populate your textfields
            self.accountLabel.text = currentInformation.account
            ....
        }
    }
    

    Hope that makes sense and helps you.