在完成方法之前数组为空

时间:2017-07-25 12:50:07

标签: ios arrays swift

我犯了一个我找不到的错误。数组(类级别)在返回之前变为空。

private func loadUserData() {
    // We're getting user info data from JSON response
    let session = Twitter.sharedInstance().sessionStore.session()
    let client = TWTRAPIClient.withCurrentUser()
    let userInfoURL = "https://api.twitter.com/1.1/users/show.json"
    let params = ["user_id": session?.userID]
    var clientError : NSError?
    let request = client.urlRequest(withMethod: "GET", url: userInfoURL, parameters: params, error: &clientError)
    client.sendTwitterRequest(request) { (response, data, connectionError) -> Void in
        if connectionError != nil {
            print("Error: \(connectionError)")
        }

        do {
            let json = JSON(data: data!)
            if let userName = json["name"].string,
                let description = json["description"].string,
                let followersCount = json["followers_count"].int,
                let favouritesCount = json["favourites_count"].int,
                let followingCount = json["friends_count"].int,
                let lang = json["lang"].string,
                let nickname = json["screen_name"].string {

                self.userData.append(userName)
                self.userData.append(description)
                self.userData.append(String(followersCount))
                self.userData.append(String(favouritesCount))
                self.userData.append(String(followingCount))
                self.userData.append(lang)
                self.userData.append(nickname)
                print(self.userData)
            }

        }
    }
    print(userData)
}

我只是试图从代码的其他部分访问其值,并且因为它变空而无法执行。我第一次打印时可以看到数组数据,但第二次没有。 非常感谢你!

2 个答案:

答案 0 :(得分:3)

client.sendTwitterRequest异步请求,需要网络连接。处理需要时间。

您应该提供一个返回userData的闭包,并在请求返回时访问它。

private func loadUserData(_ callback: @escaping () -> ()) {
    // We're getting user info data from JSON response
    let session = Twitter.sharedInstance().sessionStore.session()
    let client = TWTRAPIClient.withCurrentUser()
    let userInfoURL = "https://api.twitter.com/1.1/users/show.json"
    let params = ["user_id": session?.userID]
    var clientError : NSError?
    let request = client.urlRequest(withMethod: "GET", url: userInfoURL, parameters: params, error: &clientError)
    client.sendTwitterRequest(request) { (response, data, connectionError) -> Void in
        if connectionError != nil {
            print("Error: \(connectionError)")
        }

        do {
            let json = JSON(data: data!)
            if let userName = json["name"].string,
                let description = json["description"].string,
                let followersCount = json["followers_count"].int,
                let favouritesCount = json["favourites_count"].int,
                let followingCount = json["friends_count"].int,
                let lang = json["lang"].string,
                let nickname = json["screen_name"].string {

                self.userData.append(userName)
                self.userData.append(description)
                self.userData.append(String(followersCount))
                self.userData.append(String(favouritesCount))
                self.userData.append(String(followingCount))
                self.userData.append(lang)
                self.userData.append(nickname)

                callback()     
            }
        }
    }
}

func manageUserData() {
    loadUserData() {
        print(userData)
    }
}

答案 1 :(得分:1)

通过扩展@ the4kman答案解释OP的问题。

您的代码在dispatch / block中。一段时间后调用dispatch / block。

因此,您的第一个打印件会立即被调用,此时userdata为空。但在第二种情况下,在块中调用print,并将数据分配给userData。因此,当调用第二个打印时,userdata具有值。

请检查下面我提到的第一次和第二次打印的代码。

实际上,在打印行上放置断点并检查何时调用哪一行。

let request = client.urlRequest(withMethod: "GET", url: userInfoURL, parameters: params, error: &clientError)
client.sendTwitterRequest(request) { (response, data, connectionError) -> Void in
    if connectionError != nil {
        print("Error: \(connectionError)")
    }

    do {
        let json = JSON(data: data!)
        if let userName = json["name"].string,
            let description = json["description"].string,
            let followersCount = json["followers_count"].int,
            let favouritesCount = json["favourites_count"].int,
            let followingCount = json["friends_count"].int,
            let lang = json["lang"].string,
            let nickname = json["screen_name"].string {

            self.userData.append(userName)
            self.userData.append(description)
            self.userData.append(String(followersCount))
            self.userData.append(String(favouritesCount))
            self.userData.append(String(followingCount))
            self.userData.append(lang)
            self.userData.append(nickname)
            print(self.userData) // 2. print second
        }

    }
}
print(userData) // 1. print first
}

@ the4kman回答的解释

他使用了回调函数,即当您在被调用函数中接收数据时,回调用于获取调用函数中的数据。在这里他回答说他不使用任何参数,但你可以发送你的数组。

注意在您调用的func中,您可以获取块中的数据。因此,要像您的情况一样获取块内的数据,您必须使用completionhandler。

请参考:

How does a completion handler work on iOS?

  

修改

在你的func中,做出这样的改变。

func loadUserData( completion: (myArray: [String]) -> Void) { // my array is array of string. Assuming you'r passing array of string from closure.

// Write the below line where you wanted to call callback or return through closure. 
// Recommandated to use below line in second print.

    completion(userData) // 'userData' is the array which you wanted to pass from closure.

}

如何致电关闭。

loadUserData {
    (result: [String]) in
    print("got back: \(result)")
}

注意:您可能需要将关闭更改为@escaping,因为此x代码会为您提供建议。所以首先尝试我的编辑答案。