So, in my previous question, I ended up figuring out my own issue, (I would recommend taking a look at that before reading this one), but the 20 seconds of glory was cut short when I realized that the outcome was similar across all users on the app, which is what I didn't want and totally forgot about.
With the function down below, I can purchase the event and the buttons will show up for that event and go away if I cancel, and it's unique for each event, which I adore. Now, the problem with the function down below is that if I make a purchase on user1 account and the buttons show up and stay there how they're supposed to, when I log into user2 account and perhaps want to purchase that same event, the buttons are already showing up even though user2 hasn't done anything.
getSchoolDocumentID { (schoolDocID) in
if let schID = schoolDocID {
self.db.document("school_users/\(schID)/events/\(self.selectedEventID!)").getDocument { (documentSnapshot, error) in
if let error = error {
print("There was an error fetching the document: \(error)")
} else {
guard let docSnap = documentSnapshot!.get("purchased") else {
return
}
if docSnap as! Bool == true {
self.viewPurchaseButton.isHidden = false
self.cancelPurchaseButton.isHidden = false
self.creditCard.isHidden = true
self.purchaseTicketButton.isHidden = true
} else {
self.creditCard.isHidden = false
self.purchaseTicketButton.isHidden = false
}
}
}
}
}
So i tried to solve the problem on my own but ran into a roadblock. I tried to make a subcollection of events_bought
when users purchase an event and have the details stored in fields that I can call later on in a query. This was something I thought I could use to make the purchases unique amongst all users.
The function below looks through events_bought
subcollection and pulls up a field and matches it with a piece of data on the displayedVC, the issue is if the event hasn't been purchased and I go on it with that user, it crashes and says how the document reference path has the wrong number of segments which I don't get because it's the same as the function above, so I realized that the path wouldn't exist and tried to figure out ways to validate the path and came up with the function down below.
getEventsBoughtEventID { (eventBought) in
if let idOfEventBought = eventBought {
let docPath = self.db.document("student_users/\(self.user?.uid)/events_bought/\(idOfEventBought)")
if docPath.path.isEmpty {
self.creditCard.isHidden = false
self.purchaseTicketButton.isHidden = false
} else {
self.db.document("student_users/\(self.user?.uid)/events_bought/\(idOfEventBought)").getDocument { (documentSnapshot, error) in
if let error = error {
print("There was an error trying to fetch this document: \(error)")
} else {
guard let docSnapEventName = documentSnapshot!.get("event_name") else {
return
}
if docSnapEventName as! String == self.selectedEventName! {
self.viewPurchaseButton.isHidden = false
self.cancelPurchaseButton.isHidden = false
self.creditCard.isHidden = true
self.purchaseTicketButton.isHidden = true
}
}
}
}
}
}
I wasn't really sure if it would work or not so I tried my luck, but I still end up getting the same document reference errors. If anyone can figure out how I can validate a document path and use logic to make certain things happen, that would be great. Thanks.
So i finally figured out how to come about doing this. It was a 4 hour grind and struggle but i got it, with a few bugs of course. So i found out the reason my app crashed was not just because of the path segments, but cause of the fact that the idOfEventBought
didn't exist for some events because those events weren't purchased yet and that there was no subcollection called events_bought
even created yet.
Firstly, I added a test document in a subcollection called events_bought
when a user signs up, which makes sense because it would have to be made eventually anyways.
db.document("student_users/\(result?.user.uid)/events_bought/test_document").setData(["test": "test"])
This line of code allowed me to come up with my next method, that can verify if an event was bought or not.
func checkIfUserMadePurchase(shouldBeginQuery: Bool) -> Bool {
if shouldBeginQuery == true {
getEventsBoughtEventID { (eventBought) in
if let idOfEventBought = eventBought {
self.docListener = self.db.document("student_users/\(self.user?.uid)/events_bought/\(idOfEventBought)").addSnapshotListener(includeMetadataChanges: true) { (documentSnapshot, error) in
if let documentSnapshot = documentSnapshot {
if documentSnapshot.exists {
self.creditCard.isHidden = true
self.purchaseTicketButton.isHidden = true
self.viewPurchaseButton.isHidden = false
self.cancelPurchaseButton.isHidden = false
}
}
}
}
}
return true
} else {
creditCard.isHidden = false
purchaseTicketButton.isHidden = false
viewPurchaseButton.isHidden = true
cancelPurchaseButton.isHidden = true
return false
}
}
I used this method to verify if the event has been purchased yet, and if it hasn't show the right buttons.
I then call it in the process of when the purchase button in my UIAlertController
is pressed.
self.checkIfUserMadePurchase(shouldBeginQuery: true)
Lastly, I create a function that uses logic to verify is the event has been purchased, and if it has been purchased, do something specific. I then call this function in the viewDidLoad()
, viewWillAppear()
, and viewWillDisappear()
.
func purchasedStatusVerification() {
db.collection("student_users/\(user?.uid)/events_bought").whereField("event_name", isEqualTo: self.selectedEventName!).getDocuments { (querySnapshot, error) in
if let querySnapshot = querySnapshot {
if querySnapshot.isEmpty {
self.checkIfUserMadePurchase(shouldBeginQuery: false)
} else {
self.checkIfUserMadePurchase(shouldBeginQuery: true)
}
}
}
}
With all this in place, my app runs how i want to, I can successfully purchase an event and it won't show up in another users account. There are a few bugs like when a new event is created, the wrong and the right buttons are all displayed, but the wrong buttons go away after logging in and out. Also, the isHidden()
method moves pretty slow, when i load the vc and the event has a status of purchased, the purchaseTicketButton
is there for a split second, then disappears, which is quite annoying. All in all, I figured it out, and will try to improve it near production time.