【发布时间】:2015-07-23 19:07:40
【问题描述】:
我正在为基于字典数组的图像创建异步 NSURLConnections,每个字典都有自己的图像 URL:
var posts = [
["url": "url0", "calledIndex": 0],
["url": "url1", "calledIndex": 1],
["url": "url2", "calledIndex": 2],
["url": "url3", "calledIndex": 3]
]
鉴于连接的异步特性(这是我想要的,首先加载最快的图像),图像可能以不同的顺序加载,例如:
url0
url2
url3
url1
但是,如果图像被乱序加载,则需要根据图像加载的时间重新组织原始的posts 数组。因此,鉴于上述示例,posts 现在应该如下所示:
var posts = [
["url": "url0", "calledIndex": 0],
["url": "url2", "calledIndex": 2],
["url": "url3", "calledIndex": 3],
["url": "url1", "calledIndex": 1]
]
在 Swift 中有什么方法可以将特定索引处的数组值与不同索引处的同一数组的值交换?我首先尝试使用swap 函数:
// Index the images load
var loadedIndex = 0
func connectionDidFinishLoading(connection: NSURLConnection) {
// Index of the called image in posts
let calledIndex = posts["calledIndex"] as! Int
// Index that the image actually loaded
let loadedIndex = loadedIndex
// If the indicies are the same, the image is already in the correct position
if loadedIndex != calledIndex {
// If they're not the same, swap them
swap(&posts[calledIndex], &posts[loadedIndex])
}
}
然后我尝试了没有swap 函数的类似操作:
// The post that was actually loaded
let loadedPost = posts[calledIndex]
// The post at the correct index
let postAtCorrectIndex = posts[loadedIndex]
posts[calledIndex] = postAtCorrectIndex
posts[loadedIndex] = loadedPost
但是,在这两种情况下,数组值都没有正确交换。我意识到这是一个逻辑错误,但我没有看到错误的实际位置。
据我所知,它第一次交换正确,但是新字典的 calledIndex 值不正确,导致它交换回原来的位置。
这个假设可能是完全错误的,我意识到我很难描述这种情况,但我会尝试提供尽可能多的说明。
我做了一个测试用例,你可以download the source code here。它的代码是:
var allPosts:Array<Dictionary<String, AnyObject>> = [
["imageURL": "http://i.imgur.com/aLsnGqn.jpg", "postTitle":"0"],
["imageURL": "http://i.imgur.com/vgTXEYY.png", "postTitle":"1"],
["imageURL": "http://i.imgur.com/OXzDEA6.jpg", "postTitle":"2"],
["imageURL": "http://i.imgur.com/ilOKOx5.jpg", "postTitle":"3"],
]
var lastIndex = 0
var threshold = 4
var activeConnections = Dictionary<NSURLConnection, Dictionary<String, AnyObject?>>()
func loadBatchInForwardDirection(){
func createConnection(i: Int){
allPosts[i]["calledIndex"] = i
var post = allPosts[i]
let imageURL = NSURL(string: post["imageURL"] as! String)
if imageURL != nil {
let request = NSMutableURLRequest(URL: imageURL!, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 60)
let connection = NSURLConnection(request: request, delegate: self, startImmediately: true)
if connection != nil {
activeConnections[connection!] = post
}
}
}
let startingIndex = lastIndex;
for (var i = startingIndex; i < startingIndex + threshold; i++){
createConnection(i)
lastIndex++
}
}
func connection(connection: NSURLConnection, didReceiveData data: NSData) {
if activeConnections[connection] != nil {
let dataDict = activeConnections[connection]!["data"]
if dataDict == nil {
activeConnections[connection]!["data"] = NSMutableData(data: data)
} else {
(activeConnections[connection]!["data"] as! NSMutableData).appendData(data)
}
}
}
var loadedIndex = 0
func connectionDidFinishLoading(connection: NSURLConnection) {
let loadedPost = activeConnections[connection]!
activeConnections.removeValueForKey(connection)
let data = loadedPost["data"] as? NSData
let calledIndex = loadedPost["calledIndex"] as! Int
println(calledIndex)
swap(&allPosts[calledIndex], &allPosts[loadedIndex])
//(allPosts[calledIndex], allPosts[loadedIndex]) = (allPosts[loadedIndex], allPosts[calledIndex])
loadedIndex++
done(loadedIndex)
}
func done(index: Int){
if index == 4 {
println()
println("Actual: ")
println(allPosts[0]["postTitle"] as! String)
println(allPosts[1]["postTitle"] as! String)
println(allPosts[2]["postTitle"] as! String)
println(allPosts[3]["postTitle"] as! String)
}
}
func applicationDidFinishLaunching(aNotification: NSNotification) {
loadBatchInForwardDirection()
println("Loaded: ")
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
输出是:
已加载: 1 0 2 3
实际: 0 1 2 3
但是,预期的“实际”输出应该是:
1 0 2 3
值得注意的是,使用元组代码会产生略微不稳定的结果,但与实际顺序不符。您可以通过取消注释该行来了解我的意思。
【问题讨论】:
-
你的
posts定义是不合法的 Swift。这是您的实际代码吗?你看到什么问题?posts真的是 SwiftArray,还是NSArray或NSDictionary以其他方式定义的? -
@RobNapier 哎呀,我简化了数组,但忘记了键周围的引号。我将编写一个测试用例,希望能说明问题,完成后我会发布它。
-
为什么不直接通过指定一个闭包来进行比较?
-
@RobNapier 用示例测试用例更新了帖子。我可能错过了一些愚蠢的东西,但它已经成为我一直盯着的问题之一,没有任何帮助!
-
@neo 这比使用
swap或 Rob 的元组代码更好吗?