Array of objects and Table View - arrays

I have an Array of objects like this:
var Dogs : [Dog] = [Dog]()
To give you an example it looks like this when you print it :
[Dog {
name = Dog1;
age = 9;
}, Dog {
name = Dog2;
age = 4;
}]
I want to show this element in a Table View so I use this classical function :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.titleLabel.text = Dogs[indexPath.row]["name"]! as? String
return cell
}
But I get an ERROR :
fatal error: Array index out of range

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
let dog = Dogs[indexPath.row]
cell.titleLabel.text = dog.name
return cell
}

Related

How to sort my array in my tableview by Date

I am trying to return the following cells sorted by date. I have searched many posts but I can't really understand where I specifically put the sort by:
let sortedArray = jogs.sorted { $0.jogDate < $1.jogDate }
This is the function I use in my TableViewController:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoCellIdentifier") as? ToDoCell else {
fatalError("Could not dequeue a cell")
}
cell.delegate = self
let jog = jogs[indexPath.row]
cell.titleLabel?.text = jog.title
cell.descriptionLabel.text = jog.notes
cell.dateLabel.text = Jog.jogDateFormatter.string(from: jog.jogDate)
return cell
}
Or should I put the sort in the Struct file? Also would a Class file be better than a Struct file?
1. Sort your jogs by date
override func viewDidLoad() {
super.viewDidLoad()\
jogs.sort { $0.jogDate < $1.jogDate }
tableView.reloadData()
}
or
2. Use your sorted array in UITableViewDelegate / Datasource implements
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoCellIdentifier") as? ToDoCell else {
fatalError("Could not dequeue a cell")
}
cell.delegate = self
let jog = sortedArray[indexPath.row] // sorted array
cell.titleLabel?.text = jog.title
cell.descriptionLabel.text = jog.notes
cell.dateLabel.text = Jog.jogDateFormatter.string(from: jog.jogDate)
return cell
}

Use arrays from tableView if statement in another viewcontrollers

I need to create two "help" arrays according to if results in table view.
My main problem is: How can I use this arrays in another view controller?
etc.: Beacause when I want to use one array in another controller with TableViewController().helpArrayOne it is empty/or not exist in tableViewController, but after print in tableViewController I get values, thanks.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as UITableViewCell
let listOfStudents = allUrl.reduce(into: [String:String]()){$0[$1.id] = $1.stringValue}
for key in listOfStudents{
// Compare data
if cell.textLabel?.text == key.key {
cell.imageView!.image = UIImage(named:"false_icon")
var helpArrayOne:[String] = []
helpArrayOne.append(all[indexPath.row].id)
var helpArrayTwo:[String] = []
helpArrayTwo.append(all[indexPath.row].stringValue)
break
} else {
cell.imageView!.image = UIImage(named:"true_icon")
}
}
print(helpArrayOne,helpArrayTwo)
return cell
}
Remember scope; declare the arrays as instance variables that are optionals. Then you will be able to pass them into another view controller from anywhere else in the scope of the current view controller.
Just make sure that they are being passed after the value has been assigned to them.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { [weak self] in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as UITableViewCell
let listOfStudents = allUrl.reduce(into: [String:String]()){$0[$1.id] = $1.stringValue}
for key in listOfStudents{
// Compare data
if cell.textLabel?.text == key.key {
cell.imageView!.image = UIImage(named:"false_icon")
self?.helpArrayOne.append(all[indexPath.row].id)
self?.helpArrayTwo.append(all[indexPath.row].stringValue)
break
} else {
cell.imageView!.image = UIImage(named:"true_icon")
}
}
print(helpArrayOne,helpArrayTwo)
return cell
}

Display only similar compared data into table view

I have question which is little bit similar as my previous, but different.
There is a code description:
I have 2 Json arrays which I try to compare in my code -> all and allUrl. When array all contains some id from array allUrl image table row should be change to red, or vice versa green.
And my new question:How can I display only "red_icon" data in table?This data should be similar for this two arrays.thanks
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as UITableViewCell
cell.textLabel?.text = all[indexPath.row].id
cell.detailTextLabel?.text = all[indexPath.row].timestampValue
let listOfStudentsUrl = allUrl.reduce(into: [String:String]()){$0[$1.id] = $1.timestampValue}
// Compare data
listOfStudentsUrl.forEach{ key in print(key)
if cell.textLabel?.text == key.key {
cell.imageView!.image = UIImage(named:"red_icon")
break
}else{
cell.imageView!.image = UIImage(named:"green_icon")
}}
return cell
}
Correct working code after discussion below:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as UITableViewCell
let listOfStudentsUrl = allUrl.reduce(into: [String:String]()){$0[$1.id] = $1.timestampValue}
// Compare data
listOfStudentsUrl.forEach{ key in print(key)
if all[indexPath.row].id == key.key {
cell.textLabel?.text = all[indexPath.row].id
cell.detailTextLabel?.text = all[indexPath.row].timestampValue
cell.imageView!.image = UIImage(named:"red_icon")
cell.isHidden = false
break
}else{
cell.isHidden = true
}}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var rowHeight:CGFloat = 0.0
let listOfStudentsUrl = allUrl.reduce(into: [String:String]()){$0[$1.id] = $1.timestampValue}
for key in listOfStudentsUrl{
if all[indexPath.row].id == key.key{
rowHeight = 49.0
break
}else{
rowHeight = 0.0
}}
return rowHeight
}
So, you are trying to hide some specific cells of your TableView.
One way you could do this is hiding your cell and then setting it's height to zero.
To hide it, use the property .isHidden.
To change it's height, override the function heightForRowAtIndexPath.
See this for more: Hide UITableview cell

TableView with all the Idioms

I have a tableView and I would like to show to the user a list of the languages, and the user can select one or more spoken languages. Is there a way for swift to show a list of it?
In yourTableViewControlloer
let langues = ["Mandarin","Spanish","English","Hindi","Arabic","Portuguese","Bengali","Russian","Japanese","Punjabi"]
Override following two function
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
cell.textLabel?.text = langues[indexPath.row]
return cell
}
and
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let cell = tableView.cellForRowAtIndexPath(indexPath)
if (cell?.accessoryType == UITableViewCellAccessoryType.Checkmark){
cell!.accessoryType = UITableViewCellAccessoryType.None;
}else{
cell!.accessoryType = UITableViewCellAccessoryType.Checkmark;
}
}
This will give you the option to select multiple row item as follows

Cannot subscript a value of type [String] with an index of type [NSIndexPath] - prepareForSegue

I'm trying to send multiple rows from a UITableView to another UITableView using prepareForSegue function.
When I just send one option to the 2nd UITableView, the app works perfectly, BUT when I'm choose multiple rows and send those to the second UITableView as a header (for example, if I click first in "a" row, then "d" row and then "c" row... the second UITableView just show me the row "c" as a header, not the other 2 rows), it gives an error.
Pic of the error:
These are the lines I wrote for the first UITableView:
let array = ["a", "b", "c", "d", "e"]
#IBOutlet var initialTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
initialTableView.allowsMultipleSelection = true
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segueA" {
if let destination = segue.destinationViewController as? Content {
if let selectedRows = initialTableView.indexPathsForSelectedRows {
destination.title = array[selectedRows]
}
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellA", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.text = array[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let cell = tableView.cellForRowAtIndexPath(indexPath)
if (cell?.accessoryType == UITableViewCellAccessoryType.Checkmark) {
cell!.accessoryType = UITableViewCellAccessoryType.None
} else {
cell!.accessoryType = UITableViewCellAccessoryType.Checkmark
}
}
The second view contains these lines:
var contentArray:[String] = []
#IBOutlet var contentTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
contentArray.append(title!)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return contentArray.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellContent = tableView.dequeueReusableCellWithIdentifier("cellContent", forIndexPath: indexPath) as UITableViewCell
cellContent.textLabel!.text = "Second test"
return cellContent
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return contentArray[section]
}
So, if I wanna choose multiples rows and send these from the first to the second UITableView... how can I solve this error?
Thanks.
Your problem is that selectedRows is an array of NSIndexPaths. You can't use that to index into your array. You need to pass an array of Strings to your second view controller instead of just setting a single string.
Use map to select the strings from array to pass to the contentArray property of the destination viewController:
destination.contentArray = selectedRows.map { array[$0.row] }
You'll need to decide a new sensible setting for destination.title.
You'll want to remove this line from viewDidLoad:
contentArray.append(title!)

Resources