使用 Parse Server 在 Swift 循环中迭代 For

Iterating For In Loop In Swift Using Parse Server

我有一个充满用户的聊天室,当然还有一个用户名数组。我想获取与用户名关联的个人资料图片,以便为用户名数组中的每个用户排序。但是,Parse 只能按我知道的 ascending/descending 顺序排序。

因此,我需要弄清楚接收到的数据如何排序。 我最终会附加一个 url 用作图片。

    func getPics(_ completionHandler: @escaping () -> Void) {
    let query = PFQuery(className: "_User")
    
    var dictionary: [String : Int] = [:]
    var unit = 0
    for username in usernameArray {
        unit += 1
        dictionary[username] = unit
    }
    query.findObjectsInBackground(block: { (objects: [PFObject]?, error: Error?) in
    if let objects = objects {
        for object in objects {
                if error == nil {
                    for user in self.usernameArray {
                    let pfuser = object["username"] as! String
                    if pfuser == user {
                    let imageFile = object["profilePic"] as? PFFileObject
                    let imageFileString = imageFile?.url as! String
                    if let url = URL(string: imageFileString) {
                        let replacedImageUrlString = imageFileString.replacingOccurrences(of: "[removed for privacy]", with: "removed for privacy")
                        let url = replacedImageUrlString as NSString
                        self.urlArray.append(url)
                        }
                                }
                            }
                        }
        }
                     completionHandler()
                }
            })
    }

我不知道 Parse 服务器,所以我真的不知道是否存在以特定顺序获取响应的规定,如果存在那应该是最佳解决方案。但是您的解决方案存在一个普遍问题,即 时间复杂度 。 你有两个嵌套的 for 循环,这使得它的 worst case complexity 成为 O(n^2),我想你至少可以做的是将其复杂度降低到 O(n)

func getPics(_ completionHandler: @escaping () -> Void) {
    let query = PFQuery(className: "_User")

    var dictionary: [String : Int] = [:]
    var unit = 0
    for username in usernameArray {
        unit += 1
        dictionary[username] = unit
    }
    query.findObjectsInBackground(block: { (objects: [PFObject]?, error: Error?) in
        if let objects = objects, error == nil {
            let objectsDict = Dictionary(grouping: objects, by: { [=10=]["username"] as! String /* typically you should be accessing [=10=].username, but again am not aware of  PFObject */})
            for user in self.usernameArray {
                if let pfuser = objectsDict[user]?[safe: 0] as? PFObject {
                    let imageFile = pfuser["profilePic"] as? PFFileObject
                    let imageFileString = imageFile?.url as! String
                    if let url = URL(string: imageFileString) {
                        let replacedImageUrlString = imageFileString.replacingOccurrences(of: "[removed for privacy]", with: "removed for privacy")
                        let url = replacedImageUrlString as NSString
                        self.urlArray.append(url)
                    }
                }
            }
            completionHandler()
        }
    })
}

一旦你得到PFObject的数组,你就可以创建一个以用户名为键,PFObject为值的字典,一旦你有了字典,你就可以得到特定用户名的PFObject O(1),因此您可以 运行 一个 for 循环,将代码的复杂性降低到 O(n)

P.S 如果您想知道 [safe: 0] 是什么,您可以添加这个方便的扩展以安全地访问数组中特定索引处的对象

link: Safe (bounds-checked) array lookup in Swift, through optional bindings?

extension Collection {
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

P.P.S: 我的回答完全忽略了 Dictionary(grouping: API 本身的复杂性,我试图寻找信息, 但找不到。但我认为它 O(n) 不太确定,不管它是什么,如果它不是 O(n^2) 你仍然会受益