Reputation: 37
I want make QuoteApp with such a structure example :
{
"Books": {
"firstBook": {
"Quotes": {
"Quote1": "",
"Quote2": "",
"Quote3": ""
},
"name": "firsBook"
},
"secondBook": {
"Quote": {
"Quote1": "",
"Quote2": "",
"Quote3": ""
},
"name": "secondBook"
}
},
"Serials": {
"firstSerial": {
"Quote": {
"Quote1": "",
"Quote2": "",
"Quote3": ""
},
"name": "firsSerial"
},
"secondSerial": {
"Quote": {
"Quote1": "",
"Quote2": "",
"Quote3": ""
},
"name": "secondSerial"
}
}
I created a structure in Firestore
I have Category -> documents (Books, Film, Serial) in which there is "name" and contains collections (firstFilm, secondFilm...) -> documents in which there is "quote"
https://i.sstatic.net/wp0pu.png
https://i.sstatic.net/KhFSq.png
I put category name to tableView like this:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var myTableView: UITableView!
var array: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
myTableView.delegate = self
myTableView.dataSource = self
let db = Firestore.firestore()
db.collection("Category").getDocuments { (snapshot, error) in
if error != nil {
print(error)
} else {
for document in (snapshot?.documents)! {
if let name = document.data()["name"] as? String {
self.array.append(name)
DispatchQueue.main.async {
self.myTableView.reloadData()
}
}
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let category = array[indexPath.row]
cell.textLabel?.text = category
return cell
}
Its work good, but how can I catch and put data to another View, form didSelectItemAt indexPath func and show From Films -> tap -> show all collections (firstFilm+ secondFilm...)
Upvotes: 1
Views: 1587
Reputation: 684
Hey there Andrew I'm going to give you the answer to what you asked and then also make you reconsider the way you have designed out your Firestore schema as its not optimal at all and will get very complex easily and Firestore does warn of this here:
https://firebase.google.com/docs/firestore/manage-data/structure-data
Now since firstFilm
and firstBook
and all the other first_
are collections you will need to call another fetch on the Firestore like this to get the contents of that first_
(keep in mind the contents and not the collections itself) like this:
db.collection("Category").document("Film").collection("firstFilm").getDocuments
Also to make things more general usually this is the pattern that Firestore follows:
db.collection("Collection Name").document("documentId").collection("Collection Name").....
As you can see since first_
second_
are collections you can't fetch them to show in your next table view to the user to select first_
second_
. You would statically need to add these to your app so that you can show to the user that he can select something called first_
. This is bad because lets say you add an Article
category tomorrow you would to statically add firstArticle
, secondArticle
, thirdArticle
.
Moreover the documentId
mentioned above is retrievable from snapshot?.documents.documentID
. You would need to keep reference to it to be able to complete the path to fetch the rest of the nested objects in your initial collection.
So the answer is to show firstFilm
, secondFilm
, thirdFilm
you would need to handle this manually as Firestore won't return what collections exist in a document, you have to manually reference these collections and give a path to Firestore to fetch the documents at that path.
Now as you might realized that the way you have designed is not very optimum and not scalable. I really suggest that you find a way to design more generically so you could make the best of Firestore. Do go over the Firestore documentation and put more thought into it.
My initial suggestion might be instead of making firstFilm
, secondFilm
collections make a field in Film
that takes an Array
of Films. Then that way you could pass the films to the second view controller and create the table view in your second view controller. However, still this might not be optimum you can make it still more generic if you try harder.
Upvotes: 1