TableView on simulator is not referencing correctly - swift

Hello and how is everyone?
When I run the simulation of my application I go to select the first object in the table. Nothing happens. I then go and select the second object and it performs the action that the first object was supposed to. Basically the first object is not active until I select it and then select another object.
Maybe this will help:
I turn the simulator on. I select the first object nothing happens(I have a print("what row I selected") within the didSelect function to make sure it is working.). But again no printout until I hit the second object, the second object should print #1 row selected but it says #0 row selected and then performs the segue setup for 0#. After I come back from the segue the first object still performs the same.
Here is my tableView Code:
var objects: NSMutableArray! = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
self.objects.addObject("help")
self.objects.addObject("me")
self.objects.addObject("please")
self.objects.addObject("thankyou")
self.tableView.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(self.objects.count)
return self.objects.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableViewCell
cell.titleLabel.text = self.objects.objectAtIndex(indexPath.row) as? String
return cell
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
Thanks for the help.

Related

Enable unique actions for each row in UITableView

I have a small tableview of 7 rows. I would like to enable different actions for a press of each row.
For example, the row at index 0 would display another VC (without passing data). The row at index 0 would open a web URL, the next might be a share function, etc.
My biggest problem is the first case of send the user to another VC. Mostly because I don't know if I should enable a segue. And for all cases, I need to be able to specify a function for each row separately, therefore I would need to specify the proper index (0,1,2,etc).
How can I do this is Swift?
Here is a skeleton of code you need:
class ViewController: UITableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 2 }
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = String(describing: indexPath)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
print("Do action for row 0")
} else if indexPath.row == 1 {
print("Do action for row 1")
}
}
}

Saving Data in UITableview

I have an app whereby a user can add books to a favourites list, by populating a tableview. Details on the book are displayed in a view and by tapping a 'favourites', a segue is performed inputting info on that book into a tableview cell.
At present only one book can appear in the table at a time adding a new book will remove the initial entry (so in effect only the first cell of the tableview is ever used)
Is there a way to save each entry in the tableview so in effect a list of favourites is created
saveButton
#IBAction func saveButton(_ sender: Any) {
let bookFormat = formatLabel.text
if (bookFormat!.isEmpty)
{
displayMyAlertMessage(userMessage: "Please Select a Book Format")
return
}
else{
self.performSegue(withIdentifier: "LibViewSegue", sender: self)
}
}
TableView
extension LibrarybookViewController: UITableViewDataSource, UITableViewDelegate{
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 115
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(#function, dataSource.count)
return dataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print(#function, "indexPath", indexPath)
guard let bookCell = tableView.dequeueReusableCell(withIdentifier: "libCell", for: indexPath) as? LibrarybookTableViewCell else {
return UITableViewCell()
}
let libbook = dataSource[indexPath.row]
bookCell.cellTitleLabel.text = libbook.title
bookCell.cellReleaseLabel.text = libbook.release
bookCell.cellFormatLabel.text = bookFormat
return bookCell
}
I have been reading about defaults and CoreData but I'm not sure whether this should be implemented within the segue button action or within the tableview functions?
I see you have a dataSource array which contains list of books. At the simplest you could just append data to your dataSource, then reload your UITableView. But if you want persistent storage, you could look into local db solutions like SQLite, CoreData, or Realm. Then it would just be the matter of storing -> get data -> display on UITableView.
The general idea would be on add button tap (or whatever event listener you want to attach the action to), save it to persistent storage, reload your tableView, since the dataSource is from persistent storage, it'll update automatically. Suppose you load the data from persistent storage.
Also, don't store your array in UserDefaults, it's for bite sized data for things like user session etc.
Edit: as #Leo Dabus point out, indeed you can insert row without reloading the tableView by using
let index = IndexPath(row: items.count - 1, section: 0) // replace row with position you want to insert to.
tableView.beginUpdates()
tableView.insertRows(at: [index], with: .automatic)
tableView.endUpdates()

Xcode tables refresh on button click

I have a table which is populated with JSON. It works as a calendar. When the date is clicked, the table below should be populated with the events for that day.
These populate the tables after the data has been found but only does it once.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return(GlobalVar.TodaysEvents.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath) as! WhitelistTableViewCell
cell.startTime.adjustsFontSizeToFitWidth = true
print(GlobalVar.TodaysEventsTimes[indexPath.row])
cell.startTime.text = (GlobalVar.TodaysEventsTimes[indexPath.row] as! String)
cell.Summary.text = GlobalVar.TodaysEvents[indexPath.row] as? String
return(cell)
}
I have seen other posts like this and they use:
self.tableView.reload()
However, when i try this, it doesn't recognise "tableView" and simply doesn't work.
Any advice would be appreciated, thanks in advance
create a reference to your tableView ( New Referencing Outlet ) and then do this :
yourTableView.reloadData()
I don't know where you are reload the tableview but i think you reload the table view at different thread. That's why please reload the table view after inserting the data in array.

Select cell in TableView Section

I have been searching for an answer on how to do this, but nothing seems straight forward, or the user wants to do something different(like selecting multiple cells).
Background:
I am making an app about retrieving quotes everyday for different professions such as Reading, gardening, sports. I have a UITabBarController with 3 tabs.
First tab = Quote ; Second tab = Categories ; Third tab = Settings *
The Settings tab is a UITableView with 3 sections, and 2 cells in each section.
Problem: I want to make each cell go to a different destination. The first cell in the first section will just be a view controller with a slider(color slider to change text color)(will get to that later). How would I be able to accomplish this?
import UIKit
class settingsTab: UIViewController, UITableViewDelegate {
struct Objects {
var sectionName : String!
var sectionObjects : [String]!
}
var objectsArray = [Objects]()
override func viewDidLoad() {
super.viewDidLoad()
objectsArray = [Objects(sectionName: "Options", sectionObjects: ["Change color of text" , "Notifications"]),Objects(sectionName: "Extras", sectionObjects: ["Remove ads" , "Restore purchases"]),Objects(sectionName: "Support", sectionObjects: ["Rate this app" , "Email developer"]), Objects(sectionName: "Jordan Norris - Quote Daily 2016", sectionObjects: [])]
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell!
cell.textLabel?.text = objectsArray[indexPath.section].sectionObjects[indexPath.row]
cell.backgroundColor = UIColor.cyanColor()
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objectsArray[section].sectionObjects.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return objectsArray.count
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String?{
return objectsArray[section].sectionName
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
}
This is settingsTab.swift, where the TableViewController is established. If you need any more information, just comment what you would like to be added and I'll edit this post immediately. Thank you in advance!
You can access each section and each row through your last function didSelectRowAtIndexPath using indexPath.section and indexPath.row. For example if you want to access the second section and the first row, you can do
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Section \(indexPath.section), Row : \(indexPath.row)")
if indexPath.section == 1 && indexPath.row == 0{
//Code to implement View Controller to remove adds
print("Remove Adds")
}
}
Try selecting each row to show which section it prints and which row.
Will the number of sections and items in the section change? If not, creating static cells and hooking up a segue to each cell to a different destination can be done with no code (all in Interface Builder).

Why does my app crash on "indexPath.row" load?

I may not be providing enough information to properly ask this question, but I am trying to discern why I am getting a crash when my code reaches the loading of indexPath.row.
With much of the code truncated, here is my TableViewController.swift:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return minions.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return minionCellAtIndexPath(indexPath)
}
func minionCellAtIndexPath(indexPath:NSIndexPath) -> MinionCell {
let minion = minions[indexPath.row]
//Set the cell to be the custom, reusable, MinionCell
let cell = tableView.dequeueReusableCellWithIdentifier(minionCellIdentifier, forIndexPath: indexPath) as! MinionCell
if let name = minion.name {
cell.nameLabel?.text = minion.name
} else {
cell.nameLabel?.text = "No data available."
}
return cell
}
From what I can discern, the let minion = minions[indexPath.row] is throwing an error, with the error occurring on __Thread 1__ and the syntax showing:
function signature specialization Arg[0] = Owned To Guaranteed
The console output seems to show nothing indicating what the error may be, though I'm questioning if this has to do with my transition to Swift 2 from Swift 1.2.
problem should be with dequeueReusableCellWithIdentifier,Ensure it is set properly in storyboard.Best place to give identifier name for your cell is, your minioncell class.
I ended up resolving this issue by altering;
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return minionCellAtIndexPath(indexPath)
}
to
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
By altering the return function and adding all of my table cell configuration to this function, I found complete success in properly populating the table.