new to Swift: How to update the detailTextLabel?.text - ios

I'm new to Swift and working on a small project.
I have two UITableViewController: TableViewController and DetailViewController.
Click on TableViewController cell will navigate to DetailViewController.
Click on DetailViewController cell will navigate back to TableViewController and update the detailTextLabel?.text with selected item.
The problem right now is I don't know how to update the detailTextLabel?.text.
I can pass the selected data from DetailViewController to TableViewController but not sure how to update the cell.
class TableViewController: UITableViewController,DataSelectedDelegate{
var sessions=[Session]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.sessions = [Session(Game: "Game", Detail: "SuperTrack"),Session(Game: "Type",Detail : "Race")]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func userSelectedInformatiom(info:NSString){
//cell.detailTextLabel?.text=info
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sessions.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
var session:Session
session=sessions[indexPath.row]
cell.textLabel?.text = session.Game
cell.detailTextLabel?.text = sessions[indexPath.row].Detail
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail"{
let detailVC:DetailViewController = segue.destinationViewController as DetailViewController
detailVC.delegate=self
}
}
}
DetailViewController:
import UIKit
protocol DataSelectedDelegate{
func userSelectedInformatiom(info:NSString)
}
class DetailViewController: UITableViewController {
var types=[GameType]()
var test:String!
var delegate:DataSelectedDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.types = [GameType(Type:"Race"),GameType(Type:"Shoot"),GameType(Type:"Kid"),GameType(Type:"Adult")]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return types.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//let identifier: String = "tableCell"
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cells", forIndexPath: indexPath) as UITableViewCell
var type:GameType
type=types[indexPath.row]
cell.textLabel?.text = type.Type
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//println("You selected cell #\(indexPath.row)!")
//let selectedCell = tableView.cellForRowAtIndexPath(indexPath)
//selectedCell?.accessoryType = .Checkmark
if (delegate != nil){
let selectedIndex:NSString=types[indexPath.row].Type
delegate!.userSelectedInformatiom(selectedIndex)
self.navigationController?.popViewControllerAnimated(true)
}
}
}

There are multiple possible solutions:
You can pass the selected cell to the detailViewController in prepareForSegue (the sender object is the tapped cell). Then you can pass that information back in your delegate call.
You can examine the indexPath of the selected row in the delegate function userSelectedInformatiom via self.tableView.indexPathForSelectedRow(). With that indexPath you get the cell via cellForRowAtIndexPath.
You can store a reference to the selected cell before the segue is performed
...

Related

Segue not firing from custom tableView cell

I'm experiencing what I'm sure is a beginner's mistake. I have a TableViewController that should segue to a second TableViewController upon selection of a custom cell.
I've segued to a UIViewController from a custom cell in the past but I can't figure out for the life of me why this segue isn't firing. Here's the code for the entire controller that should be firing the segue. Thanks in advance!
import UIKit
class SourcesViewController: UITableViewController {
var sources: [Source] = []
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.isNavigationBarHidden = false
self.navigationItem .setHidesBackButton(true, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sources.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell_01", for: indexPath) as? SourceCell
else {
return tableView.dequeueReusableCell(withIdentifier: "cell_01", for: indexPath)
}
let currentSource = sources[indexPath.row]
cell.sourceLabel.text = currentSource.name
return cell
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let indexPath = tableView.indexPathForSelectedRow {
let sourceToSend = sources[indexPath.row]
if let destination = segue.destination as? ArticlesViewController {
destination.source = sourceToSend
}
}
}
}
Your segue doesn't get called because you are not invoking it. UIViewController has perfromSegue method that you should use for that purpose.
From what I see you would want to perform the segue after tapping the cell. To achieve this add UITableViewDelegate method and perform segue from there:
/// - SeeAlso: UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "your_identifier_from_the_storyboard", sender: nil)
}

UITableView - Not showing

I have set up tableview many times but don't why is not it showing anything. I have added a tableview on my storyboard file, added reference on ViewController file and set datasource and delegate on storyboard. on viewDidLoad registered the cell and finally added reusableIdentifier on TableViewCell. Here is my code with details configuration :
import UIKit
struct ViewControllerConstants {
static let kCellIdentifier = "TableViewCell"
static let kNibName = "TableViewCell"
}
class ViewController: UIViewController {
var cellImageNames : [String] = ["image1","image2","image3","image4","image5","image6"]
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.register(UINib.init(nibName: ViewControllerConstants.kNibName, bundle: nil), forCellReuseIdentifier: ViewControllerConstants.kCellIdentifier)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
self.tableView.reloadData()
}
}
extension ViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellImageNames.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: ViewControllerConstants.kCellIdentifier, for: indexPath) as? TableViewCell {
cell.contentImageView.image = UIImage.init(named: cellImageNames[indexPath.row])
return cell
}
return UITableViewCell.init()
}
}
extension ViewController : UITableViewDelegate {
}
Try to remove identifiers for cells in storyboard.
Problem: Cell height was not defined on code. So it was creating cell with 0 height value .
Solution: Need to specify height of each row as below code:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}

Not receiving data in detailview

I have a TableView that when the user clicks it needs to show a detail view displaying the name of the row it clicked. I populate the tableView using a Json call but I can't figure out what I'm doing wrong.
This is my bits of code of ViewController
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var valueToPass:String!
#IBOutlet weak var tableView: UITableView!
// Instantiate animals class
var items = [animalObject]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
addDummyData()
}
func addDummyData() {
RestManager.sharedInstance.getRandomUser(onCompletion: {(json) in
if let results = json.array {
for entry in results {
self.items.append(animalObject(json: entry))
}
DispatchQueue.main.sync{
self.tableView.reloadData()
}
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") as! CustomTableViewCell!
let animal = self.items[indexPath.row]
cell?.label.text = animal.name
return cell! //4.
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You selected cell #\(indexPath.row)!")
// Get Cell Label
// let indexPath = tableView.indexPathForSelectedRow!
var currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell
print(currentCell.textLabel?.text)
valueToPass = currentCell.textLabel?.text
print(valueToPass)
performSegue(withIdentifier: "detailView", sender: indexPath)
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if (segue.identifier == "detailView") {
// initialize new view controller and cast it as your view controller
let viewController = segue.destination as! DetailViewController
// your new view controller should have property that will store passed value
viewController.passedValue = valueToPass
}
}
}
and my detailView only has the following info
#IBOutlet weak var tooPass: UILabel!
var passedValue: String!
override func viewDidLoad() {
super.viewDidLoad()
print("DETAILS")
print(passedValue)
tooPass.text = passedValue
}
I'm not sure if the preparedToSegue is firing a little bit earlier because my terminal looks like this:
I used as a reference the following question any guidance will be appreciated
Try this for didSelectRowAt method.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
valueToPass = self.items[indexPath.row]
print(valueToPass)
performSegue(withIdentifier: "detailView", sender: indexPath)
}
Just pass the entire item in the items array.
Make the DetailViewController's passed item of type item. Then just access item.whateverPropertyRequired.
The problem is that in your cellForRow method, you are casting your cell to CustomTableViewCell type while in your didSelectRow, you are casting it as UITableViewCell. Change
var currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell
in your didSelectRow to
var currentCell = tableView.cellForRow(at: indexPath)! as CustomTableViewCell
Good approach here is to use view model. Create model which contains your items and data associated with them. And at segue pass your data model. It’s bad coding, getting data right from cell on didSelect method, unless some ui working on that cell

How to make a click on cell of a Table View in Swift

This is my first day in the awesome SWIFT language, I'm trying to populate a Table view with some data, everything seems to work fine, but I want to make my Table view clickable and print the id of the item clicked but it doesn't seem to be working I'm not getting any Error.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var categories = [Category]()
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return categories.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = categories[indexPath.row].Label
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
}
override func viewDidLoad() {
super.viewDidLoad()
let reposURL = NSURL(string: "http://myserver.com/file.json")
// 2
if let JSONData = NSData(contentsOfURL: reposURL!) {
// 3
if let json = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: nil) as? NSDictionary {
// 4
if let reposArray = json["List"] as? [NSDictionary] {
// 5
for item in reposArray {
categories.append(Category(json: item))
}
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
It seems like you have forgotten to set your UITableViewDelegate:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
}
If you haven't defined your tableView as a variable in your code. You can define your delegate and datasource using storyboard.

Swift using view from other controller as the background of a uitableview

I am new to swift and am trying to create an app with a table view which can use the view from another UIView controller.
Is it doable?
If so please help me with it, I have attached my code for the main controller below. Please let me know if anything is wrong?
Thank you so much.
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var numbers:[String] = []
let vc = bgViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.backgroundView = vc.view
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(numbers.count == 0){
tableView.backgroundView?.hidden = false
println("1")
}
else{
tableView.backgroundView?.hidden = true
}
return numbers.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
return cell
}
}
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var numbers:[String] = []
var vc: bgViewController!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
vc = self.storyboard.instantiateViewControllerWithIdentifier("bgViewController") as! bgViewController
tableView.backgroundView = vc.view
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(numbers.count == 0){
tableView.backgroundView?.hidden = false
println("1")
}
else{
tableView.backgroundView?.hidden = true
}
return numbers.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
return cell
}
}
Provide storyboard identifier as bgViewController in attribure inspector.

Resources