Ios 从API填充数组时可能出现计时问题

Ios 从API填充数组时可能出现计时问题,ios,swift,alamofire,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 Ala

我试图用从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语句):

你有点时间问题

您按顺序启动几个请求—循环一些数据,并对每个数据点执行异步请求

一旦请求完成,就向数组中添加一些数据。到目前为止还不错

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


因此,您要么必须处理您的顺序不确定的事实,要么为其实现一些逻辑/顺序。基于userIf或名称或其他什么-您的决定。

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

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()
}
var collabsArray=Array(计数:usersArray.count,repeatedValue:nil)
//创建调度组以进行协调
let group=dispatch\u group\u create()

对于0中的userIndex..由于执行网络操作的时间不确定,因此附加到
secImageUrls
的URL也将不确定。同样不清楚的是,为什么要分配到主队列(以及为什么要分配两次而不是一次),然后一件可能应该被分配到主队列的事情(
self.tableView.reloadData()
)不是…在数组初始化中有冗余的
()
-
[[String]](
)。还有,为什么要在异步块中处理响应?@mixel以何种方式处理
()
冗余?没有它,代码就不能工作。@luk2302我的意思是
[[String]]()
而不是
[[String]](())
也可以工作。@mixel啊,我明白了,对不起!谢谢你的回答!你能给我解释一下这个例子中的队列逻辑吗?真的,对于类似的事情,我会重构工作流程,以便表格单元格加载图像并根据需要重新显示自己,以便单个单元格在数据可用时刷新,但这是一个完全不同的问题和答案。你是在问关于dispatch_group_*的问题吗?这可能是“类似于”的问题的一部分,你实际上想实现什么还不太清楚:)再看一遍,我可能在你使用collab的地方使用了secImageUrls?在这种情况下,您可以使用collab替换所有secimageURL,然后在_notify调用中附加到secimageURL。是的,完全正确。无论如何,我正在尝试构建一个超级数组(secImageUrls),用于在表视图的每个单元格上存储多个图像的URL。@dpstart我说过调度组吗?不因为我不喜欢它们,所以必须按照我说的对数组进行排序。
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()
}