在特定指数处交换数组值?

Cha*_*lie 8 arrays cocoa swift

我正在NSURLConnections基于一组字典创建异步图像,每个字典都有自己的图像URL:

var posts = [
    ["url": "url0", "calledIndex": 0],
    ["url": "url1", "calledIndex": 1],
    ["url": "url2", "calledIndex": 2],
    ["url": "url3", "calledIndex": 3]
]
Run Code Online (Sandbox Code Playgroud)

鉴于连接的异步性质(这是我想要的,最快的图像首先加载),图像可能以不同的顺序加载,例如:

url0
url2
url3
url1
Run Code Online (Sandbox Code Playgroud)

但是,如果图像无序加载,则posts需要根据加载图像的时间重新组织原始数组.所以,鉴于上面的例子,posts现在应该是这样的:

var posts = [
    ["url": "url0", "calledIndex": 0],
    ["url": "url2", "calledIndex": 2],
    ["url": "url3", "calledIndex": 3],
    ["url": "url1", "calledIndex": 1]
]
Run Code Online (Sandbox Code Playgroud)

在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])
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我尝试了类似的东西没有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 
Run Code Online (Sandbox Code Playgroud)

但是,在这两种情况下,都没有正确交换数组值.我意识到这是一个逻辑错误,但我没有看到错误究竟在哪里.

据我所知,它第一次正确交换,但新词典的calledIndex值不正确,导致它换回原来的位置.

这个假设可能是完全错误的,我意识到我很难描述这种情况,但我会尝试提供尽可能多的澄清.


我做了一个测试用例,你可以在这里下载源代码.它的代码是:

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
}
Run Code Online (Sandbox Code Playgroud)

输出是:

已加载:1 0 2 3

实际:0 1 2 3

但是,预期的"实际"输出应为:

1 0 2 3

值得注意的是,使用元组代码会导致稍微不稳定的结果,但没有任何与实际顺序相匹配的结果.您可以通过取消注释该行来了解我的意思.

Rob*_*ier 14

你可以通过元组分配:

var xs = [1,2,3]   
(xs[1], xs[2]) = (xs[2], xs[1])
Run Code Online (Sandbox Code Playgroud)

但是你真正遇到了什么问题swap?以下应该工作正常:

swap(&xs[1], &xs[2])
Run Code Online (Sandbox Code Playgroud)


Cha*_*lie 2

这实际上比预期的要容易得多。由于当前加载的帖子保存在 中activeConnections,我可以简单地将allPosts加载索引处的值替换为当前加载的帖子:

allPosts[loadedIndex] = loadedPost
Run Code Online (Sandbox Code Playgroud)

我想不出这种方法有什么缺点,但如果有人想到任何缺点,请告诉我。