从API填充数组的可能时序问题

时间:2015-11-25 17:32:16

标签: ios swift alamofire

我正在尝试使用API​​获取字符串数组(url)来填充数组。

数组的类型是:

var secImageUrls = [[String]](())

但是,我认为在填充数组时我遇到了某种时序问题,因为它每次看起来都不一样,即使它们都应该是相同的。

以下是代码:

var usersN = 0

for user in usersArray {
    usersN++

    let collab = user as! String
    let r = i
    let p = usersN

    Alamofire.request(.GET, Constants.Path.rootUrl + "/api/users/?username=" + 
                            collab +  "&fields=image", headers: self.headers)
        .responseJSON {response in

            dispatch_async(dispatch_get_main_queue()){
                let singleImgArray = response.result.value?.objectAtIndex(0) as! NSDictionary
                let imageUrl = singleImgArray.objectForKey("image") as! String

                self.collabsArray.append(imageUrl)
            }

            if p == usersArray.count {
                //TO REMOVE???
                dispatch_async(dispatch_get_main_queue()){
                    self.secImageUrls.append(self.collabsArray)
                    self.collabsArray = []
                }
            }

            if r == self.jsonFeeds.count {
                self.loadingStatus = "collabsPics"
                self.tableView.reloadData()
            }
    }
}

编辑:这是现在的整个方法,使用调度组。但是,我仍然遇到数组问题(不要介意缺少else语句):

    var i = 0

    for feed in jsonFeeds {


        i++

        let feedType = feed["type"] as! Int

        if feedType == 1 {


            let usersArray : NSArray = feed["users"] as! NSArray


            let group = dispatch_group_create()


            for user in usersArray {


                let collab = user as! String

                let r = i



                dispatch_group_enter(group)

                Alamofire.request(.GET, Constants.Path.rootUrl + "/api/users/?username=" + collab +  "&fields=image", headers: self.headers)
                    .responseJSON {response in


                        let singleImgArray = response.result.value?.objectAtIndex(0) as! NSDictionary

                        let imageUrl = singleImgArray.objectForKey("image") as! String

                        self.collabsArray.append(imageUrl)

                        dispatch_group_leave(group)

                }

                dispatch_group_notify(group, dispatch_get_main_queue()) {
                    self.secImageUrls.append(self.collabsArray)
                    self.collabsArray = []
                    if r == self.jsonFeeds.count {

                        self.loadingStatus = "collabsPics"
                        print(self.secImageUrls)
                        self.tableView.reloadData()


                    }

                }

            }
        }

2 个答案:

答案 0 :(得分:1)

有点有时间问题。

按顺序启动一些请求 - 循环访问某些数据并为每个数据点执行异步请求。

请求完成后,您会将一些数据附加到数组中。到目前为止一切都很好。

但是没有人说请求必须按照他们开始的顺序完成。他们完成的顺序几乎是随机的。一个请求的计算成本可能更高,通过网络发送数据需要更长的时间等。

因此,您必须处理您的订单不具有确定性或为其实施某些逻辑/排序的事实。基于userIf或名称或其他东西 - 您的决定。

答案 1 :(得分:0)

正如我的评论和@ luk2302的回答所示,基本问题是您依靠网络操作以可靠的顺序完成。我的方法是创建一个预期结果数组,触发所有请求,将数组填充为响应,然后在完成后重新加载表。用dispatch_group包装它以进行协调,它看起来像

var collabsArray = Array<String?>(count: usersArray.count, repeatedValue: nil)

// Create a dispatch group for coordination
let group = dispatch_group_create()

for userIndex in 0..<usersArray.count {
    let user = usersArray[userIndex]
    let collab = user as! String

    // "Enter" the group, basically increments the count of operations in the group
    dispatch_group_enter(group)

    Alamofire.request(.GET, Constants.Path.rootUrl + "/api/users/?username=" + collab +  "&fields=image", headers: self.headers)
        .responseJSON {response in
            let singleImgArray = response.result.value?.objectAtIndex(0) as! NSDictionary
            let imageUrl = singleImgArray.objectForKey("image") as! String

            collabsArray[userIndex] = imageUrl

            // "leave" the group, basically decrements the count of operations in the group           
            dispatch_group_leave(group)
    }
}

// Schedule a block to execute when all the "enter" calls have been matched
// with "leave", ie., when all the network operations have finished, the block
// will be executed on the requested queue (in this case the main queue) so
// we don't have to futz with dispatch_async
dispatch_group_notify(group, dispatch_get_main_queue()) {
    secImageUrls.append(collabsArray)
    self.loadingStatus = "collabsPics"
    self.tableView.reloadData()
}