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()
}
}
!!更新: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()
}
}