UITableView will crash the app if It tries to display an array that has more than 13 elements - swift

So I'm using Swift 3.
The app works fine if I make limit equals 13 or less elements. But if I let it reads more than 13 it crashes.
Here is the code:
var CoolArray = [Event]()
var num = 0
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return CoolArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("Displaying the outputs using array[indexPath.row]")
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! Cell
let oneRow = CoolArray[indexPath.row]
cell.name.text = oneRow.name
return cell
}
var CoolArray = [Event]()
var num = 0
override func viewDidLoad() {
let request =
FBSDKGraphRequest(graphPath: "/somefacebookpag/events",
parameters: ["fields": "name,cover,place,start_time,end_time,description, owner",
"limit":"10", ],
httpMethod: "GET")
request?.start { ( connection, result, error) in
if let array = result as? [String : AnyObject]{
if let fbData = array["data"] as? [[String : AnyObject]] {
print("working")
for event in fbData {
if let nameOfEvent = event["name"] as? String,
{
print("Read array \(self.num)")
self.num += 1
let anotherOne = Event(name: nameOfEvent)
self.CoolArray.append(anotherOne)
}
}
self.tableView.reloadData()
}
}
}
}
If it helps. Commenting the code in viewDidLoad makes it work properly

Related

Swift Fatal Error index out of range while using searchbar in tableview

i try to load an json data with tableView and i wanna add search data using uiSearchBar, data is search well but when i try to hit 'x' button on the searchBar or when i try to backspace the input it crash...Any help guys? or should i change my search method? thanks for the help. I'm still new in swift so if theres a better method to search please let me know:)
struct ProjectSumName: Decodable {
let id : Int
let name : String
enum CodingKeys : String, CodingKey {
case id = "id"
case name = "name"
}
}
class ProjectSumController: UIViewController {
#IBOutlet weak var SearchBar: UISearchBar!
#IBOutlet weak var ProjectSumTableView: UITableView!
var projectSum = [ProjectSumName]()
var filterProject : [ProjectSumName] = [ProjectSumName]()
var isSearch : Bool = false
override func viewDidLoad() {
super.viewDidLoad()
SearchBar.delegate = self
Loading()
let jsonUrl = "http://\(GlobalVariable.ip):7000/api/projectApi?UserId=\(GlobalVariable.UserIdProjectSum)"
guard let url = URL(string: jsonUrl) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
do{
let projectsum = try JSONDecoder().decode([ProjectSumName].self, from: data)
self.projectSum = projectsum
self.filterProject = projectsum
DispatchQueue.main.async {
SVProgressHUD.dismiss()
self.ProjectSumTableView.reloadData()
}
}catch {
print(error)
}
}.resume()
}
}
extension ProjectSumController : UISearchBarDelegate, UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isSearch{
return filterProject.count
}else{
return projectSum.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let proc = projectSum[indexPath.row]
let proc1 = filterProject[indexPath.row]
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? ProjectSumTableCell else {return UITableViewCell()}
if isSearch{
cell.NameLbl.text = proc1.name
}else{
cell.NameLbl.text = proc.name
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let sum = projectSum[indexPath.row]
let sum1 = filterProject[indexPath.row]
if isSearch{
performSegue(withIdentifier: "Segue", sender: sum1)
let projectIDs = sum1.id
GlobalVariable.ProjectId = String(projectIDs)
}else{
performSegue(withIdentifier: "Segue", sender: sum)
let projectID = sum.id
GlobalVariable.ProjectId = String(projectID)
}
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty{
self.isSearch = false;
self.ProjectSumTableView.reloadData()
} else {
self.filterProject = self.projectSum.filter({ (ProjectSumName) -> Bool in
let tmp : NSString = NSString.init(string: ProjectSumName.name)
let range = tmp.range(of: searchText, options: NSString.CompareOptions.caseInsensitive)
return range.location != NSNotFound && range.location == 0
})
if(self.filterProject.count == 0){
self.isSearch = false;
}else{
self.isSearch = true;
}
self.ProjectSumTableView.reloadData()
}
}
"Fatal error: Index out of range
2019-06-27 09:43:46.167472+0700 ImmobiTracker[806:30114] Fatal error: Index out of range"
that crash come up everything i try to clear my searchbar...so when i try to type the first time to search its filtering the data, but when i try to clear the search bar it pop crash
There are two places where you are getting this error.
in cellForRowAt:
let proc = projectSum[indexPath.row]
let proc1 = filterProject[indexPath.row]
didSelectRowAt
let sum = projectSum[indexPath.row]
let sum1 = filterProject[indexPath.row]
Why:
You are trying to get an element from filterProject without using isSearch i.e. filterPoject array is empty. When isSearch is false then the error occurs because you are trying to get the element from the empty array.
How to Solve this:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let sum: ProjectSumName
if isSearch{
sum = filterProject[indexPath.row]
}else{
sum = projectSum[indexPath.row]
}
GlobalVariable.ProjectId = String(sum.id)
performSegue(withIdentifier: "Segue", sender: sum)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? ProjectSumTableCell else {return UITableViewCell()}
let proc: ProjectSumName
if isSearch{
proc = filterProject[indexPath.row]
}else{
proc = projectSum[indexPath.row]
}
cell.NameLbl.text = proc.name
return cell
}

Index out of range custom cell TableViewController

I'm trying to populate 3 custom cells into a TableViewController.
but I always get index out of range error. I`m not sure whats wrong with my code. anyone can help me, I'm newbie in swift.
but when i use 0 for numberOfRowsInSection return, the output is the first cell.
here's my code :
class testResize: UITableViewController {
#objc var comments = [AnyObject]()
#objc var images = [UIImage]()
var getImg = [String]()
override func viewDidLoad() {
super.viewDidLoad()
loadPosts()
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let getCom = comments[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testResizeHeadCell.self), for: indexPath) as! testResizeHeadCell
let user = getCom["nickname"] as! String
let ava = getCom["ava"] as! String
if ava != "" {
let resource = ImageResource(downloadURL: URL(string: ava)!, cacheKey: ava)
cell.avaImg.kf.setImage(with: resource)
}
cell.username.text = user
return cell
}else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testResizeCell.self), for: indexPath) as! testResizeCell
cell.setCustomImage(image: images[indexPath.row])
return cell
}else {
let getCom = comments[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testRezieTextCell.self), for: indexPath) as! testRezieTextCell
let text = getCom["text"] as! String
cell.explaination.text = text
return cell
}
}
here is my load function :
#objc func loadPosts() {
let uuid = "959D1073"
let url = URL(string: "some/url.php")!
self.tableView.reloadData()
var request = URLRequest(url: url)
request.httpMethod = "POST"
let body = "uuid=\(uuid)"
//print(body)
request.httpBody = body.data(using: String.Encoding.utf8)
URLSession.shared.dataTask(with: request) { data, response, error in
DispatchQueue.main.async(execute: {
if error == nil {
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
self.comments.removeAll(keepingCapacity: false)
self.images.removeAll(keepingCapacity: false)
self.tableView.reloadData()
guard let parseJSON = json else {
print("Error While Parsing")
return
}
guard let posts = parseJSON["posts"] as? [AnyObject] else {
print("Error while parseJSONing")
return
}
self.comments = posts.reversed()
print(self.comments)
for i in 0 ..< self.comments.count {
let path = self.comments[i]["path"] as? String
self.getImg = [path!]
if !path!.isEmpty {
let url = NSURL(string: path!)!
let imageData = try? Data(contentsOf: url as URL)
let image = UIImage(data: imageData! as Data)!
self.images.append(image)
} else {
let image = UIImage()
self.images.append(image)
}
}
self.tableView.reloadData()
//print(posts)
} catch {
print(error)
}
}else{
print(error!)
}
})
}.resume()
}
i think you have a single comment and 3 cell type and when you use indexPath.row happen some thing like this :
for example :
comments = {[{nickname : "mahdi" , ava : "url"} ]}
if indexPath.row == 0 {
let getCom = comments[0]
let user = getCom["nickname"] as! String
let ava = getCom["ava"] as! String
}else if indexPath.row == 1 {
images[1]
}else {
let getCom = comments[2]
let text = getCom["text"] as! String
}
but you have just one comment and when you call comments[1] or commens [2] , you get index out of range error
please try this code :
class testResize:UITableViewController {
#objc var comments = [AnyObject]()
#objc var images = [UIImage]()
var getImg = [String]()
override func viewDidLoad() {
super.viewDidLoad()
loadPosts()
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (self.comments.count == 0 ? 0 : self.comments.count + 2)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let getCom = comments[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testResizeHeadCell.self), for: indexPath) as! testResizeHeadCell
let user = getCom["nickname"] as! String
let ava = getCom["ava"] as! String
if ava != "" {
let resource = ImageResource(downloadURL: URL(string: ava)!, cacheKey: ava)
cell.avaImg.kf.setImage(with: resource)
}
cell.username.text = user
return cell
}else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testResizeCell.self), for: indexPath) as! testResizeCell
cell.setCustomImage(image: images[indexPath.row - 1])
return cell
}else {
let getCom = comments[indexPath.row - 2]
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: testRezieTextCell.self), for: indexPath) as! testRezieTextCell
let text = getCom["text"] as! String
cell.explaination.text = text
return cell
}
}
and change your numberOfRowInSection :
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return (self.comments.count == 0 ? 0 : self.comments.count + 2)
}
I am assuming that you load your posts asynchronously.
But you do not check if there are actually enough elements in the array. You should check if there are actually enough elements in the array before you access it with a fixed index.
Additionally, you should change your numberOfRows method to the following:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.comments.count
}
After you have loaded your posts, you can then call
self.tableView.reloadData()

Firebase tableview not populating, Swift

I have data in my db and can search for an individual record, that's working fine. But when I try to simply populate a tableview with all of the db records its not receiving/displaying any data.
here is my code:
struct drinkStruct {
let pub: String!
let rating: String!
let price: String!
}
override func viewDidLoad() {
super.viewDidLoad()
loadDrinks()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func homeClicked(_ sender: Any) {
homeClicked()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let label1 = cell.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].pub
let label2 = cell.viewWithTag(2) as! UILabel
label2.text = posts[indexPath.row].rating
let label3 = cell.viewWithTag(3) as! UILabel
label3.text = posts[indexPath.row].price
return cell
}
func loadDrinks(){
let databaseRef = Database.database().reference().child("Drinks")
ref = Database.database().reference()
databaseRef.queryOrderedByKey().observe(.childAdded, with: { (snapshot) in
if let valueDictionary = snapshot.value as? [AnyHashable:String]
{
let pub = valueDictionary["pub"]
let rating = valueDictionary["rating"]
let price = valueDictionary["price"]
self.posts.insert(drinkStruct(pub: pub, rating: rating, price: price), at: 0)
}
})
self.tableview.reloadData()
}
And here is my db structure:
Am I doing something blatantly obviously wrong? Or can anyone see what's causing no data to load?
There are no errors/unused variables etc etc.
Thanks in advance!
I think the following should do the job.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
//getting a reference to the node //
databaseRef = Database.database().reference().child("Drinks")
//observing the data changes
databaseRef.observe(DataEventType.value, with: { (snapshot) in
if snapshot.childrenCount > 0 {
// clearing the list //
self.posts.removeAll()
// iterating through all the values //
for drinks in snapshot.children.allObjects as! [DataSnapshot] {
let drinkObject = drinks.value as! [String: AnyObject]
let drinkPub = drinkObject["pub"]
let drinkRating = drinkObject["rating"]
let drinkPrice = drinkObject["price"]
//creating a drinkStruct object with the model //
let drinkModel = drinkStruct(pub: drinkPub as! String?, rating: drinkRating as! String?, price: drinkPrice as! String?)
//appending it to list
self.posts.append(drinkModel)
}
// reloading data //
self.tableView.reloadData()
}
})
}
var posts = [drinkStruct]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! YourCustomTableViewCell
let drink: drinkStruct
drink = posts[indexPath.row]
cell.label1.text = drink.pub
cell.label2.text = drink.rating
cell.label3.text = drink.price
return cell
}
}
For the newbie that's here in my footsteps, I solved this by doing a lot of things.
You need to create the tableview & cell layout in the storyboard. Then you need a cell class that dictates/assigns what's happening in each cell(imageviews, labels etc) as well as a model class for whatever you're looking up, whatever the object may be.
This is the code I used for my function in which I populate the info in the cells with the data from Firebase:
func loadDrinks(){
Database.database().reference().child("Drinks").observe(.childAdded) { (snapshot: DataSnapshot) in
if let dict = snapshot.value as? [String: Any] {
let pub = dict["pub"] as! String
let rating = dict["rating"] as! String
let price = dict["price"] as! String
let drink = Drink(pub: pub.capitalized, rating: rating.capitalized, price: price.capitalized)
self.drinks.append(drink)
print(self.drinks)
self.tableview.reloadData()
}
}
}
This was a Newbie 101 question - my bad.

Why is JSON data from local path shows incorrectly in the UITableView?

I want to parse JSON data from a local file that is available in the project and then populate these data to UITableView.
My Requirements
parse the json data from local path not from URL
Populate the json data to UITableView
Facing problems
Unable to display the parsed data, ( bracket is displaying in the table view.
I am able to print the data in console using dump() but unable to print data in tableView
Updated view controller for passing data to another controller.
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lookArrayModel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cells = myTableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let displayData = lookArrayModel[indexPath.row]
cells.textLabel?.text = String(describing: displayData.Lookname!)
cells.detailTextLabel?.text = String(describing: displayData.Lookdetails!)
// print(displayData.shadeModel)
return cells
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You selected cell #\(indexPath.row)!")
// Get Cell Label
let indexPath = myTableView.indexPathForSelectedRow;
let currentCell = myTableView.cellForRow(at: indexPath!) as UITableViewCell!;
lookNameValue = currentCell?.textLabel?.text
lookDetailValue = currentCell?.detailTextLabel?.text
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//let lookShade = LookModelData()
if (segue.identifier == "segueToLook") {
let destController:DetailsViewController = segue.destination as! DetailsViewController
//Set the selecte row index value
destController.LabelText = String(describing: lookNameValue)
destController.DetailText = String(describing: lookDetailValue)
// destController.arrayData = lookShade.shadeModel as! NSMutableArray
}
}
}
Destination view controller. Swift
class DetailsViewController:UIViewController,UITableViewDataSource,UITableViewDelegate {
var lookArrayModel = [LookModelData]()
var arrayData: NSMutableArray = []
#IBOutlet weak var secondView: UITableView!
var LabelText = String()
var DetailText = String()
var shadeText = String()
#IBOutlet weak var LookLabel: UILabel!
#IBOutlet weak var LookName: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print(arrayData)
LookName?.text = LabelText
LookLabel?.text = DetailText
secondView.dataSource = self
secondView.delegate = self
secondView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayData.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cells = secondView.dequeueReusableCell(withIdentifier: "secondCell", for: indexPath)
let displayData = arrayData
// cells.textLabel?.text = String(describing: (displayData as AnyObject))
// print(arrayData)
return cells
}
}
Please check my code :
Changed lookArrayModel type NSMutableArray to [LookModelData]. Like those I did some changes. Please check.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var lookArrayModel = [LookModelData]()
#IBOutlet weak var myTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
guard let Path = Bundle.main.path(forResource: "ColorShade", ofType: "json") else { return }
let url = URL(fileURLWithPath: Path)
do {
let data = try Data(contentsOf: url)
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
myTableView.dataSource = self
myTableView.delegate = self
//Calling the function for adding look
createLooks(dictionary: json as! NSArray)
myTableView.reloadData()
} catch {
print(error)
}
}
func createLooks(dictionary:NSArray) {
for item in dictionary {
let item1 = item as! NSDictionary
let lookModal = LookModelData()
lookModal.Lookname = item1.value(forKey: "Lookname") as? String
lookModal.LookId = item1.value(forKey: "LookId") as? String
lookModal.Lookdetails = item1.value(forKey: "Lookdetails") as? String
lookModal.shadeModel = createshade(shades: item1.value(forKey: "shades") as! NSArray)
lookArrayModel.append(lookModal)
}
}
func createshade(shades: NSArray) -> [ShadeDescription] {
var arrayShade = [ShadeDescription]()
for item in shades
{
let item1 = item as! NSDictionary
let shadeModal = ShadeDescription()
shadeModal.comboID = item1.value(forKey: "comboID") as? String
shadeModal.shadeName = item1.value(forKey: "shadeName") as? String
shadeModal.ShadeType = item1.value(forKey: "ShadeType") as? String
shadeModal.ShadeCode = item1.value(forKey: "shadeCode") as? String
arrayShade.append(shadeModal)
}
return arrayShade
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lookArrayModel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cells = myTableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let displayData = lookArrayModel[indexPath.row]
// You will get like this
// print(displayData.LookId!)
// print(displayData.Lookname!)
// print(displayData.Lookdetails!)
// print(displayData.shadeModel!)
// This is the way to get shade model data
if let shadeModels = displayData.shadeModel {
for var shadeModel in shadeModels {
print(shadeModel.comboID)
print(shadeModel.ShadeType)
print(shadeModel.shadeName)
print(shadeModel.ShadeCode)
}
}
cells.textLabel?.text = String(describing: displayData.Lookname!)
return cells
}
}
class LookModelData
{
var Lookname:String?
var LookId:String?
var Lookdetails:String?
//Shades Array
var shadeModel : [ShadeDescription]?
}
class ShadeDescription {
var ShadeType:String?
var shadeName:String?
var comboID:String?
var ShadeCode:String?
}

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 :)