Функциональные циклы при загрузке из Firebase Swift - PullRequest
0 голосов
/ 20 мая 2019

Я неожиданно получаю странные результаты от функции, которая загружает каталог пользователя из Firebase. При печати на консоли я вижу, что функция печатается 5 раз, то есть функция зацикливается Я загружаю изображение продукта из Firebase Storage асинхронно. Я вызываю эту функцию при каскадном вызове при первом входе в систему, чтобы получить обратно данные пользователя, заказы, продажи и так далее. Я думал об этой опции для пользователя, чтобы изменить iPad.

Вы видите, где функция зацикливается 5 раз?

Это функция:

static func downloadProducts(completed: @escaping (Bool) -> (), vendor: String) {
        print("Firebase.downloadProducts() : Query for products in Firebase started")
        let ref = Database.database().reference()
        ref.child("Continent").child("Europe").child("Country").child("\(UserDetails.country!)").child("Catalog").queryOrdered(byChild: "Product Vendor").queryEqual(toValue: String(describing: UserDetails.fullName!)).observeSingleEvent(of: .value) { (snapshot) in
            print("downloadProducts() : snapshot is: \(snapshot)")
            guard let data = snapshot.value as? [String: [String : String]] else { print("downloadProducts() : data is not [String: [String : String]] "); return}
            //            guard let data = snapshot.value as? [String : String] else { print("downloadProducts() : wrong type of data"); return}
            for (_, value) in data {

                let productId = value["Product Id"]!
                let vendor = value["Product Vendor"]!
                let availableQuantity = value["Available Quantity"]!
                let soldQuantity = value["Sold Quantity"]!
                let minimumStock = value["Minimum Stock"]!
                let name = value["Product Name"]!
                let price = value["Product Price"]!
                let category = value["Product Category"]!
                let description = value["Product Description"]!
                let pictureUrl = value["Product Picture Url"]!
                let url = URL(string: pictureUrl)!
                DispatchQueue.global().async {
                    let data = try? Data(contentsOf : url)
                    DispatchQueue.main.async {

                        let productImage = UIImage(data: data!)!
                        do{
                            try Product.saveProduct(completed: { (true) in
                                print("Firebase.downloadProducts() : Product from Firebase added to CoreData")
                            }, productImage: productImage, productId: productId, category: category, name: name, price: price, vendor: vendor, availableQuantity: availableQuantity, soldQuantity: soldQuantity, minimumStock: minimumStock, description: description)
                        } catch {
                            print("Firebase.downloadProducts() : Error saving product to CoreData: \(error)")
                        }
                    }
                    print("downloadProducts() : User inventory found in Firebase and saved to CoreData")
                    print("downloadProducts() : Query for products in Firebase ended")
                    completed(true)
                }
            }
        }
    }

и это каскадный вызов:

static func findUser(userName: String)  {
        print("findUser(): checkinf for User in CoreData")
        let context = CoreData.databaseContext
        let request: NSFetchRequest<User> = User.fetchRequest()
        request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: false),NSSortDescriptor(key: "logo", ascending: false)]
        request.predicate = NSPredicate(format: "name == %@", userName)
        do {
            let fetch = try context.fetch(request)
            if fetch.count > 0 {
                print(" findUser() : User is a returning user")
                for value in fetch { // user exists
                    UserDetails.shopId = value.shopId
                    UserDetails.fullName = value.name
                    UserDetails.logo = UIImage(data: value.logo! as Data )
                    UserDetails.logoUrl = value.logoUrl
                    UserDetails.address = value.address
                    UserDetails.zipCode = value.zipCode
                    UserDetails.city = value.city
                    UserDetails.region = value.region
                    UserDetails.country = value.country
                    UserDetails.phoneNumber = value.phoneNumber
                    UserDetails.latitude = value.latidute
                    UserDetails.longitude = value.longitude
                }
            } else {
                print(" findUser(): User is a 1st time user in device, will now check for user in Firebase")
                Firebase.downloadShopDetails(completed: { (true) in
                    if UserDetails.shopId == nil {
                        // user is not registered in Firebase
                        print("findUser() : User not found in Firebase, user is First time user ")
                    } else {
                        // user has been found in Firebase
                        print("findUser() : user found in Firebase, will now check for opening times in Firebase")
                        Firebase.downloadOpeningTimes(completed: { (true) in

                            print("findUser() : Opening times downloaded from Firebase, will now check for user orders in Firebase")
                            Firebase.downloadOrders(completed: { (true) in

                                print("findUser() : user orders downloaded from Firebase, will now check for user products in Firebase")
                                Firebase.downloadProducts(completed: { (true) in
                                    print("findUser() : Inventoy downloaded from Firebase")
                                }, vendor: UserDetails.fullName!)

                            })

                        }, shopName: UserDetails.fullName!)

                    }
                }, shopName: userName)
                UserDetails.shopId = UUID().uuidString
                UserDetails.fullName = userName
            }
        } catch  {
            print("findUser(): Error loading user details : \(error)")
        }
    }

Ответы [ 2 ]

0 голосов
/ 20 мая 2019

Я наконец нашел, где проблема. В Firebase.downloadOrders() я звонил complete(true) при сохранении заказов в Core Data, поэтому для каждого сохраненного заказа вызывался `Firebase.downloadProduct (). Поместил его после цикла for in и теперь продукты загружаются правильно.

0 голосов
/ 20 мая 2019

Вы называете завершение здесь много раз

DispatchQueue.global().async {
    let data = try? Data(contentsOf : url)
    DispatchQueue.main.async {

        let productImage = UIImage(data: data!)!
        do{
            try Product.saveProduct(completed: { (true) in
                print("Firebase.downloadProducts() : Product from Firebase added to CoreData")
            }, productImage: productImage, productId: productId, category: category, name: name, price: price, vendor: vendor, availableQuantity: availableQuantity, soldQuantity: soldQuantity, minimumStock: minimumStock, description: description)
        } catch {
            print("Firebase.downloadProducts() : Error saving product to CoreData: \(error)")
        }
    }
    print("downloadProducts() : User inventory found in Firebase and saved to CoreData")
    print("downloadProducts() : Query for products in Firebase ended")
    completed(true)
}

но вы должны

let g = DispatchGroup() 
for (_, value) in data {    
    ...
    ...
    ...
    DispatchQueue.global().async {
        g.enter()
        let data = try? Data(contentsOf : url)
        DispatchQueue.main.async {

            let productImage = UIImage(data: data!)!
            do{
                try Product.saveProduct(completed: { (true) in
                    print("Firebase.downloadProducts() : Product from Firebase added to CoreData")
                }, productImage: productImage, productId: productId, category: category, name: name, price: price, vendor: vendor, availableQuantity: availableQuantity, soldQuantity: soldQuantity, minimumStock: minimumStock, description: description)
            } catch {
                print("Firebase.downloadProducts() : Error saving product to CoreData: \(error)")
            }
        }
        print("downloadProducts() : User inventory found in Firebase and saved to CoreData")
        print("downloadProducts() : Query for products in Firebase ended")
        g.leave() 
    }

}
g.notify(queue:.main) {
  completed(true)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...