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"
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]
}
}
}