Как отслеживать обработанных пользователей? - PullRequest
0 голосов
/ 20 июня 2019

У меня есть такой запрос:

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]

update:

Я включил больше кода для контекста.У меня есть цикл, который зацикливается на пользователях.Внутри мне нужно определить, был ли пользователь уже обработан.

Из операторов print я обнаружил, что для многих циклов, несмотря на то, что uid отсутствует в контейнере, он не добавляет его, поскольку в следующем цикле контейнер пуст.

Ответы [ 2 ]

1 голос
/ 20 июня 2019

Если единственная цель, которую вы пытаетесь достичь, это отслеживать пользователей, которые уже были обработаны, вы можете использовать Установить вместо

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()
    })
}
1 голос
/ 20 июня 2019

Ваш код более / менее правильный.Вот упрощение, которое работает на игровой площадке, где вы можете увидеть, как работает ваша логика.Как указывает @vadian, вы не «добавляете» к dict, вместо этого вы присваиваете значение свойству, но, как указывает vdmzz, вы должны и могли бы делать это с Set.

* 1003.*

Печать:

["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 всегда будет пустым в конце цикла, потому что асинхронная задача не имеетт вернулся.Это может быть хорошо, если вы ведете постоянную запись (NSUserDefaults, CoreData) обработанных вами uid, но если это эфемерно - то есть исчезнет, ​​когда приложение закроется, вы захотите улучшить свой журнал обработкис чем-то вроде «состояния» (но есть дюжина различных способов решить его, но это не так).

Вот пример, который реализует 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...