How to get section of UITableView on a child UICollectionView - swift

I create a View Controller that contains a UITableView and each UITableViewCell contains a UICollectionView. My problem is that I can't have a different result on every CollectionView. I parse data with JSON. I have a static array but it looks like its empty.
In cellForItemAt, I get an error: Index out of range.
Here is my ViewController
import UIKit
class HomeScreenCategoriesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var moviesCategories = ["Popular", "Now Playing", "Latest", "Top Rated", "Upcoming"]
var popularMovies = MovieModel()
var nowPlayingMovies = MovieModel()
static var movies: [MovieModel] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = 130
tableView.tableFooterView = UIView()
parsePopularMovies()
parseNowPlayingMovies()
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "\(moviesCategories[section])"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "HomeScreenMovieTableViewCell", for: indexPath) as? HomeScreenCategoriesTableViewCell
{
return cell
}
return UITableViewCell()
}
func parsePopularMovies() {
let jsonUrlString = "URLwithMyAPIkey"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
let tempMovies = try
JSONDecoder().decode(MovieModel.self, from: data)
self.popularMovies.page = tempMovies.page
self.popularMovies.total_results = tempMovies.total_results
self.popularMovies.total_pages = tempMovies.total_pages
self.popularMovies.results = tempMovies.results
for i in 0..<(self.popularMovies.results?.count ?? 0) {
let tempPosterPath = "https://image.tmdb.org/t/p/w500" + (self.popularMovies.results?[i].poster_path)!!
let tempBackDropPath = "https://image.tmdb.org/t/p/w500" + (self.popularMovies.results?[i].backdrop_path)!!
self.popularMovies.results?[i].poster_path = tempPosterPath
self.popularMovies.results?[i].backdrop_path = tempBackDropPath
HomeScreenCategoriesViewController.movies.append(self.popularMovies)
}
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}
func parseNowPlayingMovies() {
let jsonUrlString = "URLwithMyAPIkey"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
let tempMovies = try
JSONDecoder().decode(MovieModel.self, from: data)
self.nowPlayingMovies.page = tempMovies.page
self.nowPlayingMovies.total_results = tempMovies.total_results
self.nowPlayingMovies.total_pages = tempMovies.total_pages
self.nowPlayingMovies.results = tempMovies.results
for i in 0..<(self.nowPlayingMovies.results?.count ?? 0) {
let tempPosterPath = "https://image.tmdb.org/t/p/w500" + (self.nowPlayingMovies.results?[i].poster_path)!!
//let tempBackDropPath = "https://image.tmdb.org/t/p/w500" + (self.nowPlayingMovies.results?[i].backdrop_path)!!
self.nowPlayingMovies.results?[i].poster_path = tempPosterPath
HomeScreenCategoriesViewController.movies.append(self.nowPlayingMovies)
}
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}
}
and here is my TableViewCell
import UIKit
class HomeScreenCategoriesTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet var collectionView: UICollectionView!
var sectionIndex:Int?
static var movies: [MovieModel] = []
override func awakeFromNib() {
super.awakeFromNib()
self.collectionView.delegate = self
self.collectionView.dataSource = self
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeScreenMovieTableViewCell", for: indexPath) as! HomeScreenCategoriesTableViewCell
cell.sectionIndex = indexPath.section
return cell
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeScreenMovieCell", for: indexPath) as! HomeScreenCategoriesCollectionViewCell
cell.test.text = HomeScreenCategoriesTableViewCell.movies[collectionView.tag].results?[indexPath.row].title!
return cell
}
}
My model is this:
struct MovieResults: Codable, Equatable {
let id: Int?
let title: String?
let overview: String?
let adult: Bool?
let original_language: String?
var poster_path: String?
var backdrop_path: String?
let vote_average: Float?
let release_date: String?
}
struct MovieModel: Codable {
var page: Int?
var total_results: Double?
var total_pages: Int?
var results: [MovieResults]?
}
I tried to follow this instruction (How to get section of UITableView from inside a child UICollectionview) but I can't​ find a solution
What am I doing wrong?

There are few issues here:
Model naming
The data model object you use is confusing. MovieModel sounds like it should represent a single movie. But looking at parsing functions,
self.nowPlayingMovies.page = tempMovies.page
self.nowPlayingMovies.total_results = tempMovies.total_results
self.nowPlayingMovies.total_pages = tempMovies.total_pages
self.nowPlayingMovies.results = tempMovies.results
it looks like there are multiple entries in that object. It should probably be called MovieCategoryModel.
HomeScreenCategoriesTableViewCell should have a model that looks like this:
var movieCategory: MovieCategoryModel!
Since you are going to have different movies in
different sections, movieCategory property should not be static.
cellForItemAt indexPath In this method you are trying to configure cell UI with the data about the movie. But the properties of HomeScreenCategoriesTableViewCell was never populated.
numberOfItemsInSection
This should return the number of movies in that section. Your code returns 5 - which is some arbitrary number. That's the issue for the error. You should return movieCategory.total_results
cellForRowAt indexPath
In HomeScreenCategoriesViewController when you dequeue HomeScreenMovieTableViewCell, you need to pass the movies to that cell, so it will have data to present. You need to do something like:
if section == 0 {
cell.movieCategory = popularMovies
} else if section == 1 {
cell.movieCategory = nowPlayingMovies
}
In general, from the parsing code, you need to save the movies separately for each category. That way in the tableView delegate methods you can easily fetch the data you need for the section.
Parsing code also needs some work, as I can see you are cycling through the items contained within the object
for i in 0..<(self.nowPlayingMovies.results?.count ?? 0)
but adding the whole object to the array within that same loop
`HomeScreenCategoriesViewController.movies.append(self.nowPlayingMovies)`
Edit based on extra information provided:
MovieResults is very confusing name for an object that represents a single Movie. I would suggest changing it to just Movie.
Then MovieModel - the object that contains multiple movies, would be a MovieCategory. Maybe it's also a good idea to store the title of that category within the object itself?
Models
struct Movie: Codable, Equatable {
let id: Int?
let title: String?
let overview: String?
let adult: Bool?
let original_language: String?
var poster_path: String?
var backdrop_path: String?
let vote_average: Float?
let release_date: String?
}
struct MovieCategory: Codable {
var title: String?
var page: Int?
var total_results: Double?
var total_pages: Int?
var results: [Movie]?
}
View Controller
import UIKit
class HomeScreenCategoriesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var moviesCategories: [MovieCategory] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = 130
tableView.tableFooterView = UIView()
parsePopularMovies()
parseNowPlayingMovies()
}
func numberOfSections(in tableView: UITableView) -> Int {
return moviesCategories.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let category = moviesCategories[section]
return category.title
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "HomeScreenMovieTableViewCell", for: indexPath) as? HomeScreenCategoriesTableViewCell
{
cell.movieCategory = moviesCategories[indexPath.section]
return cell
}
return UITableViewCell()
}
func parsePopularMovies() {
let jsonUrlString = "URLwithMyAPIkey"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
var popularMovies = try
JSONDecoder().decode(MovieCategory.self, from: data)
popularMovies.title = "Popular Movies"
for i in 0..<(popularMovies.results?.count ?? 0) {
let tempPosterPath = "https://image.tmdb.org/t/p/w500" + (popularMovies.results?[i].poster_path)!!
let tempBackDropPath = "https://image.tmdb.org/t/p/w500" + (popularMovies.results?[i].backdrop_path)!!
popularMovies.results?[i].poster_path = tempPosterPath
popularMovies.results?[i].backdrop_path = tempBackDropPath
}
self.moviesCategories.append(popularMovies)
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}
func parseNowPlayingMovies() {
let jsonUrlString = "URLwithMyAPIkey"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
var nowPlayingMovies = try
JSONDecoder().decode(MovieCategory.self, from: data)
for i in 0..<(nowPlayingMovies.results?.count ?? 0) {
let tempPosterPath = "https://image.tmdb.org/t/p/w500" + (nowPlayingMovies.results?[i].poster_path)!!
//let tempBackDropPath = "https://image.tmdb.org/t/p/w500" + (self.nowPlayingMovies.results?[i].backdrop_path)!!
nowPlayingMovies.results?[i].poster_path = tempPosterPath
}
self.moviesCategories.append(nowPlayingMovies)
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}
}
TableViewCell
class HomeScreenCategoriesTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet var collectionView: UICollectionView!
var sectionIndex:Int?
var movieCategory: MovieCategory!
override func awakeFromNib() {
super.awakeFromNib()
self.collectionView.delegate = self
self.collectionView.dataSource = self
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeScreenMovieCell", for: indexPath) as! HomeScreenCategoriesCollectionViewCell
if indexPath.row < movieCategory.results?.count ?? 0 {
let movie = movieCategory.results?[indexPath.row]
cell.test.text = movie.title
}
return cell
}
}

Related

How to identify first and last rows of each section | Swift

How can I identify the first and last rows of each section in a dynamic tableview and make a view inside the cell class hidden.
For each first cell in each section I need to hide the topView, for each last row of each section, I need to hide the bottomView.
For example I have the following Class:
class cell: UITableViewCell {
#IBOutlet weak var topView: UIView!
#IBOutlet weak var bottomView: UIView!
}
I have tried to identify the last row of each section by doing the following, but it simple does not hide the correct bottomView, except for in the last section. Is there a way to identify the rows correctly?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! cell
let item = sections[indexPath.section].items[indexPath.row]
structure = sections[indexPath.section].items
let totalRow = tableView.numberOfRows(inSection: indexPath.section)
if(indexPath.row == totalRow - 1)
{
cell.bottomView.isHidden = true
}
return cell
}
var sections = [mySections]()
var structure = [myStructure]()
Fetching Data:
private func fetchJSON() {
guard let url = URL(string: "test.com")
else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = "id=\1".data(using: .utf8)
URLSession.shared.dataTask(with: request) { data, _, error in
guard let data = data else { return }
do {
let decoder = JSONDecoder()
self.structure.sort { $0. datestamp > $1.datestamp }
let res = try decoder.decode([myStructure].self, from: data)
let grouped = Dictionary(grouping: res, by: { $0. datestamp })
let keys = grouped.keys.sorted()
self.sections = keys.map({mySections(date: $0, items: grouped[$0]!
)})
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch {
print(error)
}
}.resume()
}
Struct:
struct mySections {
let date : String
var items : [myStructure]
}
struct myStructure: Decodable {
let recordid: Int
let testname: Int
let datestamp: String
}
Example of Data:
[
{
"recordid": 1,
"testname": "Jen",
"datestamp": "2021-11-3"
},
{
"recordid": 1,
"testname": "Jake",
"datestamp": "2021-11-2"
}
]
Setting Up Sections:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let section = sections[section]
return section.items.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].date
}
When you are in your delegate creating cells, you are in the process of telling the table view what rows and sections it has. That means that the table view hasn't finished setting up sections so it's not the right time to call tableView.numberOfRows(inSection:).
You're already pulling your data out of the model... in this case it looks like your model has an array of sections and each section has an array of rows, so ask the model whether or not the cell your building is at the beginning or end of its section:
import UIKit
import SwiftUI
import PlaygroundSupport
class CustomCell : UITableViewCell {
static let identifier = "CustomCell"
}
class DataSource : NSObject, UITableViewDataSource {
let sections = [
[
"Cow",
"Duck",
"Chicken"
],
[
"Lion",
"Zebra",
"Oryx"
],
]
func numberOfSections(in tableView: UITableView) -> Int {
sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let newCell = tableView.dequeueReusableCell(withIdentifier: CustomCell.identifier, for: indexPath)
if let cell = newCell as? CustomCell {
cell.textLabel?.text = sections[indexPath.section][indexPath.row]
if indexPath.row == 0 {
cell.textLabel?.backgroundColor = UIColor.yellow
}
if indexPath.row == sections[indexPath.section].count - 1 {
cell.textLabel?.backgroundColor = UIColor.gray
}
}
return newCell
}
}
let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
tableView.register(CustomCell.self, forCellReuseIdentifier: CustomCell.identifier)
let dataSource = DataSource()
tableView.dataSource = dataSource
PlaygroundSupport.PlaygroundPage.current.liveView = tableView

Multiple CollectionView inside TableView Swift

I have a Tableview, I have a collectionView in it. There is imageView inside the CollectionView. As you can see in the photo at the moment, two TableViews are created separately. But the data in the CollectionViews inside this tableView is the same. Important: I have one collectionView. CollectionView is created according to the tableView Count. The collectionView's hps has the same data. I want to upload different data to CollectionViews, how can I do this? There is a well-known tableView for circumcision and weddings, but the CollectionView contents are the same. I have to do it differently.
For example, I want to add the data in davetiyefilee Array to 1.CollectionView. 2.I want to add the data from davetiyefilee2 Array to the CollectionView
enter image description here
enter image description here
UITableViewCell
class CategoryRow : UITableViewCell {
#IBOutlet weak var firstColView: UICollectionView!
var data = [String]()
var collectionData = [[String]]()
}
extension CategoryRow : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return collectionData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellDav1", for: indexPath) as! anaSayfaCell
let rowValue = collectionData[indexPath.row]
for i in 0..<rowValue.count {
let deneme = collectionData[firstColView.tag][indexPath.item]
let urlNew = URL(string: deneme)
cell.denemeImage.sd_setImage(with: urlNew)
}
return cell
}
func setData(data: [String])
{
self.data = data
self.firstColView.reloadData()
}
func setDataa(collectionData: [[String]])
{
self.collectionData = collectionData
self.firstColView.reloadData()
}
}
MainView
extension anaSayfaViewController : UITableViewDelegate { }
extension anaSayfaViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return kategoriIsımYeni[section]
}
func numberOfSections(in tableView: UITableView) -> Int {
return kategoriIsımYeni.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CategoryRow
cell.setData(data: davetiyefilee)
cell.setDataa(collectionData: collectionData)
return cell
}
}
class anaSayfaViewController: UIViewController, UISearchBarDelegate {
var collectionData = [[String]]()
var davetiyefilee = [String]()
var davetiyefilee2 = [String]()
#objc func davetiyeCEK1(){
if let baslik = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
for review in baslik {
if let soru_baslik = review["davetiyefilee"] as? String {
let s = String(describing: soru_baslik)
self.davetiyefilee.append(s)
self.collectionData.append([s])
DispatchQueue.main.async { self.tableViewKategoriler.reloadData() } } } }
if let baslik = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
for review in baslik {
if let soru_baslik = review["davetiyefilee"] as? String {
let s = String(describing: soru_baslik)
self.davetiyefile2.append(s)
self.collectionData.append([s])
DispatchQueue.main.async {
self.tableViewKategoriler.reloadData()
} } } }}
Swift has a handy property to its Views called tag. You can assign a unique tag to each of your CollectionViews and then add your data based on a condition like:
if collectionView.tag == 0 {
\\ your first collection view data assignment
} else if collectionView.tag == 1 {
\\ your second collection view data assignment
collectionView here refers to the parameter given by the collectionView functions above. You can assign tags using storyboard, but it is better to do that programmatically if you have many collectionViews. A good article that covers this: https://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell-in-swift/

Parsed value from array not displayed in tableview

I need to display value -> "all[0].id" into table row.
This value is id 123456 from JSON file.
Code builded without errors, but still without data in table row.
thanks for some suggestions
I parsed JSON File with this values:
{
"fields": {
"123456": {
"timestampValue": "2019-03-05T23:00:00Z"
},
"7895": {
"timestampValue": "2019-03-02T23:00:00Z"
}
},
"createTime": "2019-03-08T00:14:55.357221Z",
"updateTime": "2019-03-08T17:22:08.398718Z"
}
There is my ViewController file with tableview:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let data = DataLoader().userData
let all = [Item]()
#IBOutlet weak var tableView: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return all.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = all[0].id
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
}
There is my Code in DataLoader.swift:
public class DataLoader
{
#Published var userData = [Root]()
init()
{
load()
}
func load()
{
if let fileLocation = Bundle.main.url(forResource: "mydata", withExtension: "json")
{
// Do catch in case of error
do
{
let data = try Data(contentsOf: fileLocation)
let jsonDecoder = JSONDecoder()
let res = try jsonDecoder.decode(Root.self, from: data)
var all = [Item]()
for (id,item) in res.fields {
all.append(Item(id:id,timestampValue:item.timestampValue))
}
print(all)
}
catch
{
print(error)
}
}
}
}

I want to get firestore data in dequeueReusableCell

I rewrote all the text and now I got the code I wanted to realize.
It can not be displayed on the tableCell, and the layout also collapses. I am sorry that the code and the body I wrote are not explained enough.
guard let userID = Auth.auth (). currentUser? .uid I want to always acquire userID with else {return}.
// guard let docSnapshot = querySnapshot, document.exists else {return}
Since an error occurs, it is commented out.
Within viewidLoad of UIViewController
var profDict: [ProfDic] = [] is in the UIViewController.
profUIView is being added to UIViewController.
func getFirebaseData() {
db = Firestore.firestore()
guard let userID = Auth.auth().currentUser?.uid else {return}
let ref = db.collection("users").document(userID)
ref.getDocument{ (document, error) in
if let document = document {
// guard let docSnapshot = querySnapshot, document.exists else {return}
if let prof = ProfDic(dictionary: document.data()!) {
self.profDict.append(prof)
print("Document data \(document.data())")
}
}else{
print("Document does not exist")
}
self.profUIView.tableView1.reloadData()
}
}
tableView1 has been added to ProfUIView.
class ProfUIView: UIView, UITableViewDelegate, UITableViewDataSource {
//omission...
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .blue
addSubview(tableView1)
tableView1.anchor(top: //omission...
sections = [
Section(type: .prof_Sec, items: [.prof]),
Section(type: .link_Sec, items: [.link]),
Section(type: .hoge_Sec, items: [.hoge0])
]
tableView1.register(TableCell0.self, forCellReuseIdentifier: TableCellId0)
tableView1.register(TableCell3.self, forCellReuseIdentifier: TableCellId3)
tableView1.register(TableCell5.self, forCellReuseIdentifier: TableCellId5)
tableView1.delegate = self
tableView1.dataSource = self
}
var tableView1:UITableView = {
let table = UITableView()
table.backgroundColor = .gray
return table
}()
//omission
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (baseVC?.profDict.count)!//sections[section].items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch sections[indexPath.section].items[indexPath.row] {
case .prof:
let cell0 = tableView.dequeueReusableCell(withIdentifier: TableCellId0, for: indexPath) as? TableCell0
cell0?.nameLabel.text = baseVC?.profDict[indexPath.row].userName
return cell0!
}
//omission...
}
}
Additional notes
import Foundation
import FirebaseFirestore
struct ProfDic {
var userName :String
var dictionary:[String:Any] {
return
["userName" : userName
]
}
}
extension ProfDic {
init?(dictionary:[String:Any]) {
guard let userName = dictionary["userName"] as? String
else {return nil}
self.init(userName: userName as String)
}
}
enter image description here
First create an empty array of ProfDic elements:
var profDict: [ProfDic] = []
Then create a function to load your Firebase Data:
func getFirebaseData() {
db = Firestore.firestore()
let userRef = db.collection("users").getDocuments() {
[weak self] (querySnapshot, error) in
for document in querySnapshot!.documents {
guard let docSnapshot = docSnapshot, docSnapshot.exists else {return}
if let prof = ProfDic(dictionary: docSnapshot.data()!) {
profDict.append(prof)
}
}
tableView.reloadData()
}
}
Call this function in viewDidLoad or viewDidAppear.
Then in tableView cellForRowAt you access your data like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch sections[indexPath.section].items[indexPath.row] {
case .prof:
let cell = tableView.dequeueReusableCell(withIdentifier: TableCellId, for: indexPath) as? TableCell
cell?.nameLabel.text = profDict[indexPath.row].userName
return cell!
}
}
EDIT:
Also in numberOfRowsInSection:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return profDict.count
}

display images on collectionview inside tableview

I'm trying to display images on collectionview inside tableview.
I implemented codes like so
//Model
import UIKit
import Firebase
struct Post {
var key: String
var Date: String
var tweetImageUrl = [URL]()
var Text: String
init(snapshot: DataSnapshot) {
self.key = snapshot.key
self.Date = (snapshot.value as! NSDictionary)["Date"] as? String ?? ""
self.Text = (snapshot.value as! NSDictionary)["Text"] as? String ?? ""
if let urls = (snapshot.value as! NSDictionary)["tweetImageUrl"] as? [String:String] {
for (_,value) in urls {
if let finalUrl = URL(string: value) {
tweetImageUrl.append(finalUrl)
}
}
}
}
}
//tableviewcell
import UIKit
class TimellineTableViewCell: UITableViewCell {
#IBOutlet var profileImage: UIImageView!
#IBOutlet var tempoName: UILabel!
#IBOutlet var dateLabel: UILabel!
#IBOutlet var caption: UILabel!
#IBOutlet var collectionView: UICollectionView!
var post: Post? {
didSet {
tempoName.text = "channing"
dateLabel.text = post?.Date
caption.text = post?.Text
profileImage.image = #imageLiteral(resourceName: "heart")
}
}
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
profileImage.layer.cornerRadius = 30.0
profileImage.layer.masksToBounds = true
}
}//class
extension TimellineTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard let count = post?.tweetImageUrl.count else { return 0 }
return count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "timeLineCell", for: indexPath) as! TimelineCollectionViewCell
cell.configCell(post: post)
return cell
}
}//extension
//collectionviewcell
import UIKit
class TimelineCollectionViewCell: UICollectionViewCell {
#IBOutlet var imageView: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
}
func configCell(post: Post?) {
guard let imageUrl = post?.tweetImageUrl else { return }
for url in imageUrl {
URLSession.shared.dataTask(with: url, completionHandler: { (data, res, err) in
guard let data = data else { return }
let image = UIImage(data: data)
DispatchQueue.main.async {
self.imageView.image = image
}
}).resume()
}
}
}//class
//viewcontroller
import UIKit
import Firebase
class TimelineViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var TimelinetableView: UITableView!
var ref: DatabaseReference! {
return Database.database().reference()
}
let uid = Auth.auth().currentUser?.uid
var tweets = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
self.TimelinetableView.rowHeight = UITableViewAutomaticDimension
self.TimelinetableView.estimatedRowHeight = 300
fetchTweets()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 300
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tweets.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = TimelinetableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! TimellineTableViewCell
cell.post = tweets[indexPath.row]
return cell
}
func fetchTweets() {
ref.child("TWEETS").child(uid!).observe(.value, with: { (snapshot) in
var result = [Post]()
for post in snapshot.children {
let post = Post(snapshot: post as! DataSnapshot)
result.append(post)
}
self.tweets = result.sorted(by: { (p1, p2) -> Bool in
p1.Date > p2.Date
})
self.TimelinetableView.reloadData()
}, withCancel: nil)
}//func
}//class
But if I run it simulator looks like this
If I selected one of these cell, components come out except imageview on the collectionview. If cell is not being selected, simulator looks like a cell which says "Really fun". Does anyone have any idea how to fix this?
It's about constrains not the code. So, after I gave constrains properly it worked fine.