【问题标题】:How to keep track of processed users?如何跟踪已处理的用户?
【发布时间】:2019-06-20 18:45:26
【问题描述】:

我有这个字典:

var userDict : [String : Bool] = ["": true]

我想使用它,以便我可以快速有效地检查用户是否已被处理。问题是我无法为其添加值。正如在网上找到的流行答案中所见,我已经完成了以下操作。我该如何解决这个问题?

var processedUsers = Set<String>()
func search() {
for u in snapChildren {
            print(u, " this is one of the users")

                let uid = self.getUID(snapshot: u)

                print(" Is \(uid) in processedUsers?", processedUsers.contains(uid), " This is the entiere thing: ", processedUsers)
                if !processedUsers.contains(uid) {
                    print("hfsghfdsagfkdsafjlksadfhjklasdfhlksahfjklsadfhakd")
                    let user = User(theuserID: uid)
                    self.retrieveUsersInfo(userObj: user, completion: {
                        self.peopleArray.append(user)
                        self.processedUsers.insert(user.userID!)
                        self.tableView.reloadData()
                    })
                }

要清楚。我想添加诸如["HDSFG2323BFYDSG54": true]之类的值

更新:

我已经包含了更多的上下文代码。我有一个循环遍历用户的循环。在里面我需要确定用户是否已经被处理。

从打印语句中我发现,对于许多循环,尽管已经知道 uid 不在容器中,但它似乎没有添加它,因为在下一个循环中容器是空的。

【问题讨论】:

  • 严格来说,您不能将值追加到字典中。不过,您的代码看起来是正确的。如果uid 键的值不存在,请设置键/值对。
  • I am unable to add values to it 是什么意思?当你尝试这样做时会发生什么?
  • @Cristik 键值对,
  • 您的最新更新使它看起来更加混乱。如果您将已完成的用户添加到processedUsers,它应该可以工作。请参阅我更新的示例。如果仍然无法正常工作,请使用断点调试 retrieveUsersInfo — 您可能希望事件发生乱序。

标签: ios swift dictionary


【解决方案1】:

如果您尝试实现的唯一目标是跟踪已处理的用户,则可以改用 Set

var processedUsers = Set<String>()
...
processedUsers.insert(freshlyProcessedUsersUid) // insert
processedUsers.contains(uid) //checking if already has been processed

所以你的代码可能是这样的:

if !processedUsers.contains(uid) {
    let user = User(theuserID: uid)
    self.retrieveUsersInfo(userObj: user, completion: {
        self.peopleArray.append(user)
        self.processedUsers.insert(user.uid)
        self.tableView.reloadData()
    })
}

【讨论】:

  • 同意,Set 是解决这个问题的更合适的工具。
  • Set 不可能有重复值
【解决方案2】:

您的代码或多/少是正确的。这是一个在操场内运行的简化版,您可以在其中看到您的逻辑有效。正如@vadian 指出的那样,您不是“附加”到字典,而是为属性分配值,但正如 vdmzz 指出的那样,您应该并且可以使用Set 来做到这一点。

import UIKit

struct User {
    var uid: String
}

var processedUsers: Set<String> = Set()

var uids = ["HDSFG2323BGYDSG53", "JDSFG2323BPTDSG59", "ODSFG2323BABDSG50"]

uids.forEach({
    if !processedUsers.contains($0) {
        let user = User(uid: $0)
        processedUsers.insert(user.uid)
        print(processedUsers)
    }
})

打印:

["HDSFG2323BGYDSG53"]
["HDSFG2323BGYDSG53", "JDSFG2323BPTDSG59"]
["HDSFG2323BGYDSG53", "ODSFG2323BABDSG50", "JDSFG2323BPTDSG59"]

但是,我高度怀疑您的代码仍然无法正常工作的原因是因为 retrieveUsersInfo 的异步特性。您正在循环遍历处于空状态的整个 Set,并在检索到它之后用用户的值填充它。。这是我认为正在发生的事情的演示:

import UIKit
import PlaygroundSupport

struct User {
    var uid: String
}

func retrieveUsersInfo(uid: String, completion: @escaping (User) -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        let user = User(uid: uid)
        completion(user)
    }
}

var processedUsers: Set<String> = Set()

var uids = ["HDSFG2323BGYDSG53", "JDSFG2323BPTDSG59", "ODSFG2323BABDSG50"]

uids.forEach({
    if !processedUsers.contains($0) {
        retrieveUsersInfo(uid: $0, completion: { (user) in
            processedUsers.insert(user.uid)
            print("Callback returned", processedUsers)
        })
        print("Loop ended", processedUsers)
    }
})

PlaygroundPage.current.needsIndefiniteExecution = true

输出:

Loop ended []
Loop ended []
Loop ended []
Callback returned ["HDSFG2323BGYDSG53"]
Callback returned ["HDSFG2323BGYDSG53", "JDSFG2323BPTDSG59"]
Callback returned ["HDSFG2323BGYDSG53", "JDSFG2323BPTDSG59", "ODSFG2323BABDSG50"]

因此,您的 Set 在循环结束时将始终为空,因为异步任务尚未返回。如果您保留已处理的 uid 的持久记录(NSUserDefaults、CoreData),这可能没问题,但如果这是短暂的——这意味着它会在应用关闭时消失,您需要加强处理日志使用“状态”之类的东西(但有十几种不同的方法可以解决它,但不是这样)。

这是一个实现Hashable状态的例子:

import UIKit
import PlaygroundSupport

struct User {
    var uid: String
    var state: ProcessedState

    init(uid: String) {
        self.uid = uid
        self.state = .none
    }

    enum ProcessedState {
        case none
        case started
        case success
        case error
    }
}

extension User: Equatable {
    static func == (lhs: User, rhs: User) -> Bool {
        return lhs.uid == rhs.uid
    }
}

extension User: Hashable {
    var hashValue: Int {
        return uid.hashValue
    }
}

func retrieveUsersInfo(user: User, completion: @escaping (User) -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        var user = user
        user.state = .success // or .error
        completion(user)
    }
}

var processedUsers: Set<User> = Set()

var users: [User] = [
    User(uid: "HDSFG2323BGYDSG53"),
    User(uid: "JDSFG2323BPTDSG59"),
    User(uid: "ODSFG2323BABDSG50")]

users.forEach({ user in
    if processedUsers.first(where: { $0 == user })?.state != .success {
        var user = user
        user.state = .started
        processedUsers.insert(user)
        retrieveUsersInfo(user: user, completion: { (user) in
            print("Callback returned", processedUsers)
        })
        print("Loop ended", processedUsers)
    }
})

PlaygroundPage.current.needsIndefiniteExecution = true

【讨论】:

  • 你是对的,只能通过修复我的 willdisplay 代码来解决这个问题,你可以在这里看到:stackoverflow.com/questions/39430628/…。我正在标记另一个答案,因为那是我选择的答案。
  • 没问题,祝你好运。我添加了一个使用Hashable 支持状态属性的示例,以防万一它对您有用。
猜你喜欢
  • 1970-01-01
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
相关资源
最近更新 更多