why is my data not showing in the tableview? - swift

Printing out the data in the console works just fine. In viewdidload method the array count is also fine. But if i use any of the code outside viewdidload its not working. Im trying to populate a table with two labels in each cell (airline and price) but none of the data is displaying and when i try out in the console arrayOfFlights.price.count (for example) it prints out 0 as if its empty.
Data:
import Foundation
class FlightDataModel {
var airline: String?
var price: String?
init(airline: String?, price: String?) {
self.airline = airline
self.price = price
}
}
controller.swift
import Foundation
import UIKit
class FlightsController: UITableViewController, UITableViewDataSource {
var arrayOfFlights : [FlightDataModel] = [FlightDataModel]()
var startpoint:String!
var endpoint:String!
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrayOfFlights.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as myCustomTableViewCell
cell.airlineLabel.text = arrayOfFlights[indexPath.row].airline
cell.priceLabel.text = arrayOfFlights[indexPath.row].price
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// json request to api
let qpxRequest = Router.QPXRequest()
request(qpxRequest).responseJSON { (request, response, json, error) -> Void in
if json != nil {
//insert airline data into arrayOfFlights
if let myJSON = json as? [String:AnyObject] {
if let trips = myJSON["trips"] as? [String:AnyObject] {
if let data = trips["data"] as? [String:AnyObject] {
if let carriers = data["carrier"] as? [[String:String]] {
for (index, carrierName) in enumerate(carriers) {
var myFlight = FlightDataModel(airline: carrierName["name"] as String!, price:nil)
self.arrayOfFlights.append(myFlight)
}
}
}
if let tripOptions = trips["tripOption"] as? [[String:AnyObject]] {
for (index, tripOption) in enumerate(tripOptions) {
self.arrayOfFlights[index].price = tripOption["saleTotal"] as String!
}
}
}
}
}
} // end api request
} //end viewdidload
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
}

Make sure your class is set as dataSource of your tableView
And call the method tableView.reloadData() when you are done with the data parsing.

Related

Is there any way to list user defaults datas with swift?

I am trying to do save datas like name, address with user default at main view controller. After saving data, I wanted to list all user default data at second view controller with tableview (PeopleViewController). I managed to save user default data with main view controller. But only last saved user default data can be showed at tableview while I would like to list all data at tableview. What am I doing wrong? Can you give an idea? Thank you in advance..
My second view controller / PeopleViewController
import UIKit
class PeopleListViewController: UIViewController, UITableViewDelegate,UITableViewDataSource {
var names = [String]()
var address = [String]()
let storage = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
let peopleData = storage.value(forKey: "people") as? Data
if peopleData != nil {
let decoder = JSONDecoder()
do {
let person = try decoder.decode(People.self, from: peopleData!)
names.append(person.name)
address.append(person.address)
}catch {
print(error)
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LocationCell",for: indexPath)
cell.textLabel?.text = names[indexPath.row]
cell.detailTextLabel?.text = address[indexPath.row]
return cell
}
}
My main view controller
import UIKit
class ViewController: UIViewController {
#IBOutlet var TextFields: [UITextField]!
let storage = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
let peopleData = storage.value(forKey: "people") as? Data
if peopleData != nil {
let decoder = JSONDecoder()
do {
TextFields[0].text = ""
TextFields[1].text = ""
}catch {
print(error)
}
}
}
#IBAction func createButtonTapped(_ sender: UIButton) {
let name = TextFields[0].text!
let address = TextFields[1].text!
let people = People(
name: name,
address: address
)
let encoder = JSONEncoder()
do {
let peopleData = try encoder.encode(people)
storage.setValue(peopleData, forKey: "people")
TextFields[0].text! = ""
TextFields[1].text! = ""
}catch {
print(error)
}
}
}
My People Model
import Foundation
struct People: Codable{
var name: String
var address: String
}
Right now, you are only storing one person in UserDefaults. Every time you create a new person, you are overwriting the previous value. To store many people, you need an [People]. When you decode and encode, you can encode the whole [People].
// main VC
let encoder = JSONEncoder()
let decoder = JSONDecoder()
do {
// first decode the array from the storage
let array = storage.data(forKey: "people").map { try decoder.decode([People].self, from: $0) } ?? []
array.append(people) // add the newly created person
let newArrayData = try encoder.encode(array)
storage.set(newArrayData, forKey: "people")
TextFields[0].text! = ""
TextFields[1].text! = ""
}catch {
print(error)
}
// table VC
// you don't need two parallel arrays
var people: [People] = []
let storage = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
do {
people = try storage.data(forKey: "people").map { try decoder.decode([People].self, from: $0) } ?? []
} catch let error {
print(error)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return people.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LocationCell",for: indexPath)
cell.textLabel?.text = people[indexPath.row].name
cell.detailTextLabel?.text = people[indexPath.row].address
return cell
}

How to get section of UITableView on a child UICollectionView

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
}
}

Core Data Fetch Result Not Convert NsManaged sub class

class DeviceModel: NSManagedObject {
#NSManaged var deviceName: String?;
#NSManaged var devicePrice: String?;
}
class DeviceListController: UIViewController {
var deviceList: [Any] = [];
override func viewDidLoad() {
super.viewDidLoad();
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated);
let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate;
let context = appDelegate.persistentContainer.viewContext;
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Device");
do {
self.deviceList = try context.fetch(request);
} catch {
print(error);
}
}
}
extension DeviceListController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.deviceList.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: DeviceItemCell.reuiseIdentifier) as? DeviceItemCell else {
fatalError("Error create tableCell")
}
guard let item = deviceList[indexPath.row] as? DeviceModel else {
fatalError("Item not convertable DeviceModel");
}
cell.deviceName.text = item.value(forKey: "devicePrice") as! String
return cell;
}
}
let item = deviceList[indexPath.row] as? NSManagedObject is work but
when I change NSManagedObject to my DeviceModel class guard return
error why i dont convert item to DeviceModel class? But DeviceModel
class is sub class NsManagedObject

unable to load JSON data in tableviewcell using Alamofire & SwiftyJSON

I want to load the name & symbol of cryptocurrencies in textLabel & detailTextLabel
TableViewController.swift :-
import UIKit
import Alamofire
import SwiftyJSON
class TableViewController: UITableViewController {
var fetchCoinInfo = [[String: AnyObject]]()
let url = "https://api.coinmarketcap.com/v1/ticker/"
override func viewDidLoad() {
super.viewDidLoad()
getCoinData(url: url)
self.tableView.reloadData()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return fetchCoinInfo.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
cell.textLabel?.text = fetchCoinInfo[indexPath.row]["name"] as? String
cell.detailTextLabel?.text = fetchCoinInfo[indexPath.row]["symbol"] as? String
return cell
}
Using Alamofire :-
func getCoinData(url: String) {
Alamofire.request(url, method: .get)
.responseJSON { response in
if response.result.isSuccess {
print("Sucess! Got the data")
let coinJSON : JSON = JSON(response.result.value!)
print(coinJSON)
self.updateCoinData(json: coinJSON)
} else {
print("Error: \(String(describing: response.result.error))")
}
}
self.tableView.reloadData()
}
Using SwiftyJSON :-
func updateCoinData(json : JSON) {
if let coinData = json[].arrayObject {
print(coinData)
self.fetchCoinInfo = coinData as! [[String: AnyObject]]
}
else {
print("cannot connect to the server")
}
}
}
put this line in updateCoindata
self.tableView.reloadData()
func updateCoinData(json : JSON) {
if let coinData = json[].arrayObject {
print(coinData)
self.fetchCoinInfo = coinData as! [[String: AnyObject]]
self.tableView.reloadData()
}
else {
print("cannot connect to the server")
}
}

Swift - How can I group value array (from dictonary) to multiple section

I am a beginner in Swift. How can I group array list from dictionary? I tried, but it show all list into one section. I can't group, list, sort and show list by the same group.
Image 1
But I can do like this,
Image 2
Here's the code for Todolist array
import Foundation
import Firebase
import FirebaseDatabase
struct TodoList {
var title:String!
var content:String!
var username:String!
var dateLabel:String!
var ref : FIRDatabaseReference?
var key: String!
var picNoteStringUrl : String!
var userImageViewStringUrl : String!
var postId: String!
init(title:String,content:String,username:String,picNoteStringUrl : String,userImageViewStringUrl : String,postId: String,dateLabel:String,key:String="") {
self.title=title
self.content=content
self.username = username
self.dateLabel = dateLabel
self.key=key
self.userImageViewStringUrl = userImageViewStringUrl
self.picNoteStringUrl = picNoteStringUrl
self.postId = postId
self.ref=FIRDatabase.database().reference()
}
init(snapshot:FIRDataSnapshot) {
let value = snapshot.value as? [String: AnyObject]
title = value?["title"] as! String
content = value?["content"] as! String
username = value?["username"] as! String
postId = value?["postId"] as! String
picNoteStringUrl = value?["picNoteStringUrl"] as! String
userImageViewStringUrl = value?["userImageViewStringUrl"] as! String
dateLabel = value?["dateLabel"] as! String
key = snapshot.key
ref = snapshot.ref
}
func toAnyObject() -> [String: AnyObject] {
return ["title": title as AnyObject, "content": content as AnyObject,"username": username as AnyObject,"picNoteStringUrl":picNoteStringUrl as AnyObject,"userImageViewStringUrl": userImageViewStringUrl as AnyObject,"postId":postId as AnyObject,"dateLabel" : dateLabel as AnyObject]
}
}
And here's my code for TableViewController
class TodoListTableViewController: UITableViewController{
var storageRef: FIRStorageReference!
var databaseRef : FIRDatabaseReference!
var todoArray:[TodoList] = []
override func viewDidLoad() {
super.viewDidLoad()
if FIRAuth.auth()?.currentUser==nil{
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home")
self.present(vc,animated: true,completion: nil)
}
else{
let uid = FIRAuth.auth()?.currentUser?.uid
let databaseRef = FIRDatabase.database().reference().child("allTasks").child(uid!)
databaseRef.observe(.value, with: { (snapshot) in
var newItems = [TodoList]()
for item in snapshot.children {
let newTodo = TodoList(snapshot: item as! FIRDataSnapshot)
let letter = newTodo.dateLabel
newItems.insert(newTodo, at: 0)
}
self.todoArray = newItems
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}) { (error) in
print(error.localizedDescription)
}
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return todoArray.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let todoLine = todoArray[section]
return todoArray.count
}
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
let todoLine = todoArray[section]
return todoLine.dateLabel
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TodoTableViewCell
cell.todoItemName.text = self.todoArray[indexPath.row].title
cell.todoDescription.text = self.todoArray[indexPath.row].content
cell.usernameLabel.text = self.todoArray[indexPath.row].username
let picNoteStringUrl = self.todoArray[indexPath.row].picNoteStringUrl
let userImageViewStringUrl = self.todoArray[indexPath.row].userImageViewStringUrl
FIRStorage.storage().reference(forURL: picNoteStringUrl!).data(withMaxSize: 10 * 1024 * 1024, completion: { (data, error) in
if error == nil {
DispatchQueue.main.async(execute: {
if let picNoteStringUrl = UIImage(data:data!) {
cell.picNote.image = picNoteStringUrl
print("testpass",picNoteStringUrl)
}
})
}else {
print(error!.localizedDescription,"555")
}
})
FIRStorage.storage().reference(forURL: userImageViewStringUrl!).data(withMaxSize: 10 * 1024 * 1024, completion: { (data, error) in
if error == nil {
DispatchQueue.main.async(execute: {
if let userImageViewStringUrl = UIImage(data:data!) {
cell.userImageView.image = userImageViewStringUrl
print("testpass",userImageViewStringUrl)
}
})
}else {
print(error!.localizedDescription,"555")
}
})
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath:IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .default, title: "\u{267A}\n Delete") { action, index in
print("more button tapped")
let ref = self.todoArray[indexPath.row].ref
ref?.removeValue()
self.todoArray.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
delete.backgroundColor = UIColor.red
let check = UITableViewRowAction(style: .default, title: "\u{2611}\n check") { action, index in
print("edit button tapped")
}
check.backgroundColor = UIColor.orange
return [check, delete]
}
}
}
}
You have to organize your data by section first. I don't see that happening since you simply add all received items into one array.
Based on the screenshot you have provided and the project, it looks as if you are trying to display todo items by date where each section is for a different date. And as far as I can tell, your date value is in the dateLabel property.
If all of the above is correct, then you would need to convert the dateLabel property, which is a String, to an actual Date value so that you can work with the individual dates. Or, depending on how the date string is set up, you might be able to do the same thing by getting just the date component of the string. For example, if your date strings are like "2017-03-31 10:55am" or something, just getting the "2017-03-31" part should allow you to organize the todo items so that all items for the same date can be easily identified.
Once you do that, you have to set up some sort of a structure - if you go with date strings, then a dictionary might work - where you can identify all todo items for a given date. For example, if you have just the date extracted as a string (like "2017-03-31") then you could set up something like this:
var dates = [String]()
var todoItems = [String:[TodoList]]()
The above means that for one string value (which would be a date), you'd have an array of TodoList items. The dates array would be just a convenience so that you can sort the date strings the way you want.
Once you have that, you can modify your table delegate methods to get the count of items in dates to get the sections and the relevant TodoList for each row. Like this:
override func numberOfSections(in tableView: UITableView) -> Int {
return dates.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let date = dates[section]
let array = todoItems[date]
return array.count
}
Hopefully, the above makes sense :)