Search code examples
iosarraysswiftsegueuistoryboardsegue

Segue not working in Swift


I'm trying to pass a certain part of an array to another view controller based on which tableview cell you click on. So when I click on the third cell for example, it'll send the array data from the third cell to the next screen. This data is an array called "todos". When I try to receive the data in the next screen, there is no data.

Code:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "EditTodo" {
        print("it is")
        var vc = segue.destination as! ViewController
        // var indexPath = tableView.indexPathForCell(sender as UITableViewCell)
        var indexPath = tableView.indexPathForSelectedRow
        if let index = indexPath {
            vc.todo = todos[index.row]
        }
    }
}

I'm not sure if it's being called at all, or what. The identifier is correct, and I'm not sure what else to do. (When I run it, the print function is not called, but I'm not even sure if it's supposed to be).

Here is the whole page of code from the 'sending data' page with the table:

import UIKit
var todos: [TodoModel] = []
var filteredTodos: [TodoModel] = []

class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate {

@IBOutlet weak var tableView: UITableView!



override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
    print("i think it worked...")

    let defaults = UserDefaults.standard
    if todos.count > 0 {
        // Save what we have
        let data = NSKeyedArchiver.archivedData(withRootObject: todos)
        defaults.set(data, forKey: "TDDATA")
        defaults.synchronize()
        print("saved \(todos.count)")
    } else if let storedTodoData = defaults.data(forKey: "TDDATA"),
        let storedTodos = NSKeyedUnarchiver.unarchiveObject(with: storedTodoData) as? [TodoModel] {
        // There was stored data! Use it!
        todos = storedTodos
        print("Used \(todos.count) stored todos")

        tableView.reloadData()
        self.tableView.tableFooterView = UIView()
    }
   //print([todos.first])
    print("Here?: \(todos.first?.title)")
}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override var prefersStatusBarHidden: Bool {
    return true
}
/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if tableView == searchDisplayController?.searchResultsTableView {
        return filteredTodos.count
    }
    else {
        return todos.count
    }
}

// Display the cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    // Must use 'self' here because searchResultsTableView needs to reuse the same cell in self.tableView
    let cell = self.tableView.dequeueReusableCell(withIdentifier: "todoCell")! as UITableViewCell
    var todo : TodoModel

    if tableView == searchDisplayController?.searchResultsTableView {
        todo = filteredTodos[indexPath.row] as TodoModel
    }
    else {
        todo = todos[indexPath.row] as TodoModel
    }

    //var image = cell.viewWithTag(101) as! UIImageView
    var title = cell.viewWithTag(102) as! UILabel
    var date = cell.viewWithTag(103) as! UILabel




    //image.image = todo.image

    // image = UIImageView(image: newImage)

    // if image.image == nil{
    //    print("nilish")
    //     image = UIImageView(image: UIImage(named: "EmptyProfile.png"))
    // }


    // image.image = todo.image
    // if image.image == nil{
    //     print("pic is nil")
    //     image.image = UIImage(named: "CopyEmptyProfilePic.jpg")
    //  }



    title.text = todo.title
    date.text = "\(NSDate())"




    let locale = NSLocale.current
    let dateFormat = DateFormatter.dateFormat(fromTemplate: "yyyy-MM-dd", options:0, locale:locale)

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = dateFormat


    return cell

}

// MARK - UITableViewDelegate
// Delete the cell
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == UITableViewCellEditingStyle.delete {
        todos.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath as IndexPath], with: UITableViewRowAnimation.automatic)
        let defaults = UserDefaults.standard
        if todos.count >= 0 {
            // Save what we have
            let data = NSKeyedArchiver.archivedData(withRootObject: todos)
            defaults.set(data, forKey: "TDDATA")
            defaults.synchronize()
            print("saved \(todos.count)")
        } else if let storedTodoData = defaults.data(forKey: "TDDATA"),
            let storedTodos = NSKeyedUnarchiver.unarchiveObject(with: storedTodoData) as? [TodoModel] {
            // There was stored data! Use it!
            todos = storedTodos
            print("Used \(todos.count) stored todos")
        }

        tableView.reloadData()
    }
}

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 80
}

// Edit mode
override func setEditing(_ editing: Bool, animated: Bool) {
    super.setEditing(editing, animated: animated)
    tableView.setEditing(editing, animated: true)
}

// Move the cell
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return self.isEditing
}

// func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
//  let todo = todos.removeAtIndex(sourceIndexPath.row)
//todos.insert(todo, atIndex: destinationIndexPath.row)
//   }

// MARK - UISearchDisplayDelegate
// Search the Cell
func searchDisplayController(controller: UISearchDisplayController, shouldReloadTableForSearchString searchString: String?) -> Bool {
    //filteredTodos = todos.filter({( todo: TodoModel) -> Bool in
    //    let stringMatch = todo.title.rangeOfString(searchString)
    //    return stringMatch != nil
    //})

    // Same as below
    filteredTodos = todos.filter(){$0.title.range(of: searchString!)
        != nil}
    return true
}

// MARK - Storyboard stuff
// Unwind
@IBAction func close(segue: UIStoryboardSegue) {
    print("closed!")
    tableView.reloadData()
}

// Segue
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "EditTodo" {
        print("it is")
        var vc = segue.destination as! ViewController
        // var indexPath = tableView.indexPathForCell(sender as UITableViewCell)
        var indexPath = tableView.indexPathForSelectedRow
        if let index = indexPath {
            vc.todo = todos[index.row]
        }
    }
  }

}

How I am receiving the data in viewDidLoad of receiving screen:

nameOfDocTF.delegate = self

nameOfDocTF.text = todo?.title
outputTextView.attributedText = todo?.desc
print(todo?.title)
//prints "nil"

Solution

  • As I suspected you´re missing the didSelectRowAt function which will be called when you click on a cell and from there you need to call your prepareForSegue. Implement the following function and try:

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.performSegue(withIdentifier: "EditTodo", sender: indexPath.row)
    }
    

    And then replace your prepareForSegue function with the following:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "EditTodo" {
            let vc = segue.destination as! ViewController
            if let index = sender as? Int {
                vc.todo = todos[index]
            }
        }
    }