!更新:Firebase可能不是问题(虽然连接可能仍会暂停[?],但在ViewController主屏幕上出现了半秒的数据;尽管如此,在AddUniversal屏幕上,向Firebase数据库添加新实体也会触发相同的延迟,表明Firebase是问题[?],因为该屏幕上没有调整大小或集合视图或任何其他内容)-在ViewController屏幕上,我认为问题可能出在获取数据和将其插入collectionView单元格(卡片视图)之间Brian Voong的垂直尺码模型。我将在下面保留原始代码,并在最后保留一些Brian Voong的内容。 !!
我尝试过删除加密/解密过程,删除对GoogleAppEngine的调用(加密密钥请求),以及删除图像(仅请求文本;可能在200kB以下)。我还尝试了Frank van Puffelen的建议,在我的“一次”听众之外添加“一个”听众。什么都没有。如果我不固定此应用程序,则该应用程序将对客户不可用。
示例代码:
//
// 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系列查看垂直上浆的东西...
//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 $00.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 $00.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)
}
}
}
答案 0 :(得分:0)
我知道了!
从Firebase获取财务交易数据并不是慢点。
问题是,在获取数据之后,我先检查了所有用户的交易,从开始的银行余额开始进行调整,以使每笔交易都显示当时的当前银行余额。显然,这需要花费大量时间进行几千次交易。
通过将所有银行存款余额设置为$ 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()
}
}