Swift 请求 Firebase 数据库需要 19 秒

Swift request for Firebase database is taking 19 seconds

!!更新:Firebase 可能不是问题所在(数据在 ViewController 主屏幕上似乎在半秒内获得,尽管连接可能仍然受阻 [?];另外,在 AddUniversal 屏幕上,向 Firebase 数据库添加一个新实体触发相同的延迟,表明 Firebase 是问题 [?],因为该屏幕上没有调整大小或集合视图或任何其他内容)- 在 ViewController 屏幕上,我认为问题可能出在获取数据和插入数据之间根据 Brian Voong 的垂直尺寸模型,放入 collectionView 单元格(卡片视图)。我将在下面留下原始代码,最后留下一些 Brian Voong 的东西。 !!

我已尝试删除 encryption/decryption 进程、删除 GoogleAppEngine 调用(加密密钥请求)和删除图像(仅请求文本;可能小于 200kB)。除了我的 "once" 听众之外,我还尝试了 Frank van Puffelen 的建议,即添加一个 "on" 听众。什么都不管用。如果我不修复此应用程序,客户将无法使用它。

示例代码:

//
//  MIProcessor.swift
//  Bizzy Books
//
//  Created by Brad Caldwell on 12/19/17.
//  Copyright © 2017 Caldwell Contracting LLC. All rights reserved.
//

import UIKit
import Firebase

final class MIProcessor {

static let sharedMIP = MIProcessor()
private init() {}

public var firstTime: Bool = false
public var mIP: [MultiversalItem] = [MultiversalItem]()
public var sIP: [MultiversalItem] = [MultiversalItem]() // the search mip!
public var mipORsip: Int = Int()
public var mIPUniversals: [UniversalItem] = [UniversalItem]()
public var mIPProjects: [ProjectItem] = [ProjectItem]()
public var mIPEntities: [EntityItem] = [EntityItem]()
public var mIPAccounts: [AccountItem] = [AccountItem]()
public var mIPVehicles: [VehicleItem] = [VehicleItem]()
public var trueYou: String = String()
public var isUserCurrentlySubscribed: Bool = Bool()
private var tHeKeY: Data!
var theUser: User!
var universalsRef: DatabaseReference!
var entitiesRef: DatabaseReference!
var projectsRef: DatabaseReference!
var vehiclesRef: DatabaseReference!
var accountsRef: DatabaseReference!
var keyRef: DatabaseReference!
var obtainBalanceAfter = ObtainBalanceAfter()
var obtainProjectStatus = ObtainProjectStatus()
var balOneAfter: Int = 0
var balTwoAfter: Int = 0
var balsAfter: [Int?] = [Int?]()
var masterSearchArray: [SearchItem] = [SearchItem]()
var authorized: Bool!
var theKeyIsHere: String!

func loadTheMip(completion: @escaping () -> ()) {
    mipORsip = 0 // MIP!
    //obtainTheKey {

        self.universalsRef = Database.database().reference().child("users").child(userUID).child("universals")
        self.projectsRef = Database.database().reference().child("users").child(userUID).child("projects")
        self.entitiesRef = Database.database().reference().child("users").child(userUID).child("entities")
        self.accountsRef = Database.database().reference().child("users").child(userUID).child("accounts")
        self.vehiclesRef = Database.database().reference().child("users").child(userUID).child("vehicles")
        self.mIPUniversals.removeAll()
        self.mIPProjects.removeAll()
        self.mIPEntities.removeAll()
        self.mIPAccounts.removeAll()
        self.mIPVehicles.removeAll()
        self.universalsRef.observeSingleEvent(of: .value, with: { (snapshot) in
            for item in snapshot.children {
                self.mIPUniversals.append(UniversalItem(snapshot: item as! DataSnapshot))
            }
            self.projectsRef.observeSingleEvent(of: .value, with: { (snapshot) in
                for item in snapshot.children {
                    self.mIPProjects.append(ProjectItem(snapshot: item as! DataSnapshot))
                }
                self.entitiesRef.observeSingleEvent(of: .value, with: { (snapshot) in
                    for item in snapshot.children {
                        self.mIPEntities.append(EntityItem(snapshot: item as! DataSnapshot))
                    }
                    self.accountsRef.observeSingleEvent(of: .value, with: { (snapshot) in
                        for item in snapshot.children {
                            self.mIPAccounts.append(AccountItem(snapshot: item as! DataSnapshot))
                        }
                        self.vehiclesRef.observeSingleEvent(of: .value, with: { (snapshot) in
                            for item in snapshot.children {
                                self.mIPVehicles.append(VehicleItem(snapshot: item as! DataSnapshot))
                            }
                            let youRef = Database.database().reference().child("users").child(userUID).child("youEntity")
                            youRef.observeSingleEvent(of: .value, with: { (snapshot) in
                                if let youKey = snapshot.value as? String {
                                    self.trueYou = youKey
                                    completion()
                                }
                            })
                        })
                    })
                })
            })
        })
    //}
}

此代码在登录过程中从 ViewController.swift 调用,如下所示:

func checkLoggedIn() {

    Auth.auth().addStateDidChangeListener { auth, user in

        if user != nil {
            // User is signed in.
            userUID = (user?.uid)!
            self.theUser = user
            if user?.photoURL == nil {
            }else{
                if let imageUrl = NSData(contentsOf: (user?.photoURL)!){
                    self.profilePic.image = UIImage(data: imageUrl as Data)
                } else {
                    self.profilePic.image = UIImage(named: "bizzybooksbee")
                }
            }
            self.masterRef = Database.database().reference().child("users").child(userUID)
            self.projectsRef = Database.database().reference().child("users").child(userUID).child("projects")
            self.entitiesRef = Database.database().reference().child("users").child(userUID).child("entities")
            self.accountsRef = Database.database().reference().child("users").child(userUID).child("accounts")
            self.vehiclesRef = Database.database().reference().child("users").child(userUID).child("vehicles")
            self.youEntityRef = Database.database().reference().child("users").child(userUID).child("youEntity")
            self.firstTimeRef = Database.database().reference().child("users").child(userUID).child("firstTime")
            self.masterRef.observe(.value, with: { (snapshot) in
                print("Do NOTTTT ANY thingggggg")
            })
            self.firstTimeRef.observeSingleEvent(of: .value, with: { (snapshot) in
                if snapshot.exists() {
                    print("Do NOT any THING")
                    if self.shouldEnterLoop {
                        self.shouldEnterLoop = false
                        self.loadTheMIP()
                    }
                } else {
                    self.initializeIfFirstAppUse()
                }
            })
            print("ONE!")
            self.masterRef.observe(.childChanged, with: { (snapshot) in // GENIUS!!!!! This line loads MIP only when an item gets added/changed/deleted (and exactly WHEN an item gets added/changed/deleted) in Firebase database IN REALTIME!!!!
                print("TWO!")
                if self.shouldEnterLoop {
                    self.shouldEnterLoop = false
                    print("THREE!")
                    if MIProcessor.sharedMIP.mipORsip == 0 {
                        self.loadTheMIP()
                    } else {
                        DispatchQueue.main.async {
                            MIProcessor.sharedMIP.loadTheMip {
                                MIProcessor.sharedMIP.obtainTheBalancesAfter()
                                MIProcessor.sharedMIP.loadTheStatuses()
                                MIProcessor.sharedMIP.updateTheMIP()
                                MIProcessor.sharedMIP.updateTheSIP(i: self.thingToBeSearchedInt, name: self.thingToBeSearchedName)
                                self.cardViewCollectionView.reloadData()//Critical line - this makes or breaks the app :/
                            }
                        }
                    }

                    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5), execute: {
                        self.shouldEnterLoop = true
                    })
                }
            })
            if MIProcessor.sharedMIP.mIP.count == 0 {
                print("FOUR!")
                if self.shouldEnterLoop {
                    self.shouldEnterLoop = false
                    print("FIVE!")
                    self.loadTheMIP()
                    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5), execute: {
                        self.shouldEnterLoop = true
                    })
                }
            }
        } else {
            // No user is signed in.
            self.login()
        }
    }
}

Brian Voong collectionView vertical sizing stuff...

//Brian Voong inspiration... see if we can get vertical sizing of collectionview cells ie cardviews
extension ViewController: UICollectionViewDelegateFlowLayout {

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let i = indexPath.item
    var baseHeight: CGFloat = 150
    var sentenceOneHeight: CGFloat = 0
    var sentenceTwoHeight: CGFloat = 0
    var phoneHeight: CGFloat = 0
    var emailHeight: CGFloat = 0
    var geoHeight: CGFloat = 0
    var ssnHeight: CGFloat = 0
    var einHeight: CGFloat = 0
    var imageHeight: CGFloat = 1
    switch MIProcessor.sharedMIP.mipORsip {
    case 1: // SIP!
        switch MIProcessor.sharedMIP.sIP[i].multiversalType {
        case 1: // Project
            baseHeight = 130
            if let projectItem = MIProcessor.sharedMIP.sIP[i] as? ProjectItem {
                if projectItem.projectNotes != "" {
                    if projectItem.projectNotes.count < 30 {
                        phoneHeight = 25
                    } else if projectItem.projectNotes.count < 60 {
                        phoneHeight = 45
                    } else {
                        phoneHeight = 80
                    }
                }
                if projectItem.projectTags != "" {
                    if projectItem.projectTags.count < 30 {
                        emailHeight = 30
                    } else if projectItem.projectTags.count < 60 {
                        emailHeight = 60
                    } else {
                        emailHeight = 90
                    }
                }
                if projectItem.projectAddressStreet != "" {
                    sentenceOneHeight = 140
                } else {
                    sentenceOneHeight = 100
                }
            }
            sentenceTwoHeight = 180
        case 2: // Entity
            baseHeight = 160 //92
            if let entityItem = MIProcessor.sharedMIP.sIP[i] as? EntityItem {
                if (entityItem.phoneNumber != "") || (entityItem.email != "") || (entityItem.city != "") {
                    phoneHeight = 118
                }
                if entityItem.ssn != "" {
                    ssnHeight = 30
                }
                if entityItem.ein != "" {
                    einHeight = 30
                }
            }
        case 3: // Account
            baseHeight = 140 //92
            if let accountItem = MIProcessor.sharedMIP.sIP[i] as? AccountItem {
                if accountItem.phoneNumber != "" {
                    phoneHeight = 30
                }
                if accountItem.email != "" {
                    emailHeight = 38
                }
                if accountItem.street != "" {
                    if accountItem.city != "" {
                        if accountItem.state != "" {
                            geoHeight = 50
                        }
                    }
                }
            }
        case 4: // Vehicle
            baseHeight = 140 //92
            if let vehicleItem = MIProcessor.sharedMIP.sIP[i] as? VehicleItem {
                if vehicleItem.licensePlateNumber != "" {
                    phoneHeight = 25
                }
                if vehicleItem.vehicleIdentificationNumber != "" {
                    emailHeight = 25
                }
                if vehicleItem.placedInCommissionDate != "" {
                    geoHeight = 25
                }
            }
        default: // Universal - Ie case 0 the most frequent
            var longString = ""
            if let universalItem = MIProcessor.sharedMIP.sIP[i] as? UniversalItem {
                if universalItem.notes != "" {
                    if universalItem.notes.count < 30 {
                        phoneHeight = 25
                    } else if universalItem.notes.count < 60 {
                        phoneHeight = 45
                    } else {
                        phoneHeight = 80
                    }
                }
                imageHeight = (CGFloat(universalItem.picAspectRatio) / 1000) * widthConstraintConstant
                switch universalItem.universalItemType {
                case 1: // Personal
                    baseHeight = 100
                    longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName
                case 2: // Mixed
                    baseHeight = 160
                    switch universalItem.taxReasonId {
                    case 2: // Labor ie wc
                        longString = universalItem.whoName + universalItem.whomName + universalItem.personalReasonName + universalItem.taxReasonName + universalItem.workersCompName
                    case 5: // Vehicle
                        longString = universalItem.whoName + universalItem.whomName + universalItem.personalReasonName + universalItem.taxReasonName + universalItem.vehicleName
                    case 6: // AdMeans
                        longString = universalItem.whoName + universalItem.whomName + universalItem.personalReasonName + universalItem.taxReasonName + universalItem.advertisingMeansName
                    default: // Nothing important
                        longString = universalItem.whoName + universalItem.whomName + universalItem.personalReasonName + universalItem.taxReasonName
                    }
                case 3: // Fuel
                    baseHeight = 70
                    longString = "At 234566 miles you paid [=13=].00 to " + universalItem.whomName + " for 00.000 gallons of 87 gas in your " + universalItem.vehicleName
                case 4: // Transfer
                    baseHeight = 150
                case 6: // Project Media
                    baseHeight = 80
                default:
                    baseHeight = 120
                    switch universalItem.taxReasonId {
                    case 2: // Labor ie wc
                        longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName + universalItem.workersCompName
                    case 5: // Vehicle
                        longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName + universalItem.vehicleName
                    case 6: // AdMeans
                        longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName + universalItem.advertisingMeansName
                    default: // Nothing important
                        longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName
                    }
                }
            }
            if longString.count < 15 {
                sentenceOneHeight = 80
            } else if longString.count < 40 {
                sentenceOneHeight = 110
            } else if longString.count < 65 {
                sentenceOneHeight = 140
            } else if longString.count < 80 {
                sentenceOneHeight = 170
            } else {
                sentenceOneHeight = 200
            }
        }
        let totalHeight = baseHeight + sentenceOneHeight + sentenceTwoHeight + phoneHeight + emailHeight + geoHeight + ssnHeight + einHeight + imageHeight
        var theWidth: CGFloat = 0
        if view.frame.width < 370 { //Protection for tiny iPhones
            theWidth = view.frame.width - 20
        } else { //Good for most iphones and safe for iPads
            theWidth = 350
        }
        return CGSize(width: theWidth, height: totalHeight)
    default: // I.e. case 0 MIP!
        switch MIProcessor.sharedMIP.mIP[i].multiversalType {
        case 1: // Project
            baseHeight = 130
            if let projectItem = MIProcessor.sharedMIP.mIP[i] as? ProjectItem {
                if projectItem.projectNotes != "" {
                    if projectItem.projectNotes.count < 30 {
                        phoneHeight = 25
                    } else if projectItem.projectNotes.count < 60 {
                        phoneHeight = 45
                    } else {
                        phoneHeight = 80
                    }
                }
                if projectItem.projectTags != "" {
                    if projectItem.projectTags.count < 30 {
                        emailHeight = 30
                    } else if projectItem.projectTags.count < 60 {
                        emailHeight = 60
                    } else {
                        emailHeight = 90
                    }
                }
                if projectItem.projectAddressStreet != "" {
                    sentenceOneHeight = 140
                } else {
                    sentenceOneHeight = 100
                }
            }
            sentenceTwoHeight = 180
        case 2: // Entity
            baseHeight = 160 //92
            if let entityItem = MIProcessor.sharedMIP.mIP[i] as? EntityItem {
                if (entityItem.phoneNumber != "") || (entityItem.email != "") || (entityItem.city != "") {
                    phoneHeight = 118
                }
                if entityItem.ssn != "" {
                    ssnHeight = 30
                }
                if entityItem.ein != "" {
                    einHeight = 30
                }
            }
        case 3: // Account
            baseHeight = 140 //92
            if let accountItem = MIProcessor.sharedMIP.mIP[i] as? AccountItem {
                if accountItem.phoneNumber != "" {
                    phoneHeight = 30
                }
                if accountItem.email != "" {
                    emailHeight = 38
                }
                if accountItem.street != "" {
                    if accountItem.city != "" {
                        if accountItem.state != "" {
                            geoHeight = 50
                        }
                    }
                }
            }
        case 4: // Vehicle
            baseHeight = 140 //92
            if let vehicleItem = MIProcessor.sharedMIP.mIP[i] as? VehicleItem {
                if vehicleItem.licensePlateNumber != "" {
                    phoneHeight = 25
                }
                if vehicleItem.vehicleIdentificationNumber != "" {
                    emailHeight = 25
                }
                if vehicleItem.placedInCommissionDate != "" {
                    geoHeight = 25
                }
            }
        default: // Universal - Ie case 0 the most frequent
            var longString = ""
            if let universalItem = MIProcessor.sharedMIP.mIP[i] as? UniversalItem {
                if universalItem.notes != "" {
                    if universalItem.notes.count < 30 {
                        phoneHeight = 25
                    } else if universalItem.notes.count < 60 {
                        phoneHeight = 45
                    } else {
                        phoneHeight = 80
                    }
                }
                imageHeight = (CGFloat(universalItem.picAspectRatio) / 1000) * widthConstraintConstant
                switch universalItem.universalItemType {
                case 1: // Personal
                    baseHeight = 100
                    longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName
                case 2: // Mixed
                    baseHeight = 160
                    switch universalItem.taxReasonId {
                    case 2: // Labor ie wc
                        longString = universalItem.whoName + universalItem.whomName + universalItem.personalReasonName + universalItem.taxReasonName + universalItem.workersCompName
                    case 5: // Vehicle
                        longString = universalItem.whoName + universalItem.whomName + universalItem.personalReasonName + universalItem.taxReasonName + universalItem.vehicleName
                    case 6: // AdMeans
                        longString = universalItem.whoName + universalItem.whomName + universalItem.personalReasonName + universalItem.taxReasonName + universalItem.advertisingMeansName
                    default: // Nothing important
                        longString = universalItem.whoName + universalItem.whomName + universalItem.personalReasonName + universalItem.taxReasonName
                    }
                case 3: // Fuel
                    baseHeight = 70
                    longString = "At 234566 miles you paid [=13=].00 to " + universalItem.whomName + " for 00.000 gallons of 87 gas in your " + universalItem.vehicleName
                case 4: // Transfer
                    baseHeight = 150
                case 6: // Project Media
                    baseHeight = 80
                default:
                    baseHeight = 120
                    switch universalItem.taxReasonId {
                    case 2: // Labor ie wc
                        longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName + universalItem.workersCompName
                    case 5: // Vehicle
                        longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName + universalItem.vehicleName
                    case 6: // AdMeans
                        longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName + universalItem.advertisingMeansName
                    default: // Nothing important
                        longString = universalItem.whoName + universalItem.whomName + universalItem.taxReasonName
                    }
                }
            }
            if longString.count < 15 {
                sentenceOneHeight = 80
            } else if longString.count < 40 {
                sentenceOneHeight = 110
            } else if longString.count < 65 {
                sentenceOneHeight = 140
            } else if longString.count < 80 {
                sentenceOneHeight = 170
            } else {
                sentenceOneHeight = 200
            }
        }
        let totalHeight = baseHeight + sentenceOneHeight + sentenceTwoHeight + phoneHeight + emailHeight + geoHeight + ssnHeight + einHeight + imageHeight
        var theWidth: CGFloat = 0
        if view.frame.width < 370 { //Protection for tiny iPhones
            theWidth = view.frame.width - 20
        } else { //Good for most iphones and safe for iPads
            theWidth = 350
        }
        return CGSize(width: theWidth, height: totalHeight)
    }
}
}

我想通了!!!

从 Firebase 获取财务 t运行saction 数据不是慢点。

问题是,在获取数据后,我 运行 通过所有用户的 t运行 操作从起始银行余额开始并进行调整,以便每个 t运行 操作显示当时的银行余额。这显然需要花费大量时间来完成几千 t运行sactions。

通过将所有银行余额设置为 0.00 美元并将计算放在后台线程中,然后在完成后更新 UI,现在加载只需大约一秒钟(仍需等待 19 秒才能获取当前余额更新):

DispatchQueue.global(qos: .background).async {
                // do your job here
                MIProcessor.sharedMIP.obtainTheBalancesAfter()
                MIProcessor.sharedMIP.updateTheMIP()

                DispatchQueue.main.async {
                    // update ui here
                    self.cardViewCollectionView.reloadData()
                }
            }