I was wondering how to make a cell go to another view controller in Xcode 9, swift - ios

I've been trying to figure out how to configure a cell to go to another view, in this case, I'm listing a group of services after login and when the user taps on a service they like, it takes them to a map. But I don't know how to set the cell up in a way that it takes them to the map when its tapped. I've tried creating a segue but nothing happens when the cell is tapped. I'm new to programming and was wondering if someone could explain this.
I've watched a bunch of youtube videos which gave me the understanding on how to set up the cell (basic stuff).
Would really appreciate some advice, thanks!
Hope this post helps anyone that's dipping their feet into the programming journey!
Thank you, happy coding!
Here is the code I currently have:
import UIKit
struct cellData {
let cell : Int!
let text : String!
let image : UIImage! }
class ListServicesTVC: UITableViewController {
var arrayOfCellData = [cellData]()
override func viewDidLoad() {
arrayOfCellData = [cellData(cell : 1, text : "Barber Services", image : #imageLiteral(resourceName: "barberservice") ),
cellData(cell : 2, text : "Salon Services", image : #imageLiteral(resourceName: "salonservice"))]
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayOfCellData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if arrayOfCellData[indexPath.row].cell == 1 {
let cell = Bundle.main.loadNibNamed("BarberServiceCell", owner: self, options: nil)?.first as! BarberServiceCell
cell.barberImageView.image = arrayOfCellData[indexPath.row].image
cell.barberServicesLabel.text = arrayOfCellData[indexPath.row].text
return cell
}
else if arrayOfCellData[indexPath.row].cell == 2 {
let cell = Bundle.main.loadNibNamed("SalonServicesCell", owner: self, options: nil)?.first as! SalonServicesCell
cell.salonImageView.image = arrayOfCellData[indexPath.row].image
cell.salonServicesLabel.text = arrayOfCellData[indexPath.row].text
return cell
}
else {
let cell = Bundle.main.loadNibNamed("BarberServiceCell", owner: self, options: nil)?.first as! BarberServiceCell
cell.barberImageView.image = arrayOfCellData[indexPath.row].image
cell.barberServicesLabel.text = arrayOfCellData[indexPath.row].text
return cell
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if arrayOfCellData[indexPath.row].cell == 1 {
return 120
}
else if arrayOfCellData[indexPath.row].cell == 2 {
return 120
}
else {
return 120
}
}
}

Just follow the steps below:
create A tableView Outlet in ViewController Class.
create a TableViewCell Class and register with tableView Outlet.
then, create a DetailViewController Class ( i.e, When You click on a particular cell, it should show details of that particular cell)
In main "ViewController" do the following code
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {'
#IBOutlet var tableView: UITableView!
var tableData: [String] = ["Apple", "Samsung", "LG"]
// 1
override func viewDidLoad() {
super.viewDidLoad()
// Register customCell with tableView Outlet
let nib = UINib(nibName: "CustomTableViewCell", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "cell")
}
// 2
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData.count
}
// 3
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: CustomTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! CustomTableViewCell
// injecting data to cell
cell.lblCompanyName.text = tableData[indexPath.row]
cell.imgCompanyName.image = UIImage(named: tableData[indexPath.row])
return cell
}
// 4
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let detailObj=DetailViewController(nibName: "DetailViewController", bundle: nil)
self.navigationController?.pushViewController(detailObj, animated: true)
detailObj.nameVar=tableData[indexPath.row]
detailObj.imgStr=tableData[indexPath.row]
}
In "CustomTableViewCell" class
class CustomTableViewCell: UITableViewCell {
#IBOutlet var imgCompanyName: UIImageView!
#IBOutlet var lblCompanyName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}}
in "DetailViewController"
class DetailViewController: UIViewController {
#IBOutlet var name: UILabel!
#IBOutlet var image: UIImageView!
var nameVar:String?
var imgStr:String?
override func viewDidLoad() {
name.text=nameVar
image.image=UIImage(named: imgStr!)
super.viewDidLoad()
// Do any additional setup after loading the view.
}}
End of the Code
I think I am clear, if you have any quires just comment below.

Hi try the following set of code, I have added few additional changes in your code which is necessary for passing the details, I hope it will solve your issue.
I have added only the extra codes which you needed
class ListServicesTVC: UITableViewController {
// Add this variable in this class and use it whereever you needed it in this class
var selectedItem: cellData?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Now maintain the selected data in the local variable we declared
selectedItem = arrayOfCellData[indexPath.row]
// Now perform the segue operation
performSegue(withIdentifier: "VIEW_CONTROLLER_IDENTIFIER_OF_MAP_CLASS", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "VIEW_CONTROLLER_IDENTIFIER_OF_MAP_CLASS" {
let destinationVC = segue.destination as? VIEW_CONTROLLER_IDENTIFIER_OF_MAP_CLASS
destinationVC?.selectedItem = self.selectedItem // Pass the selected item here which we have saved on didSelectRotAt indexPath delegate
}
}
In Second class:
class VIEW_CONTROLLER_IDENTIFIER_OF_MAP_CLASS: UIViewController {
// Add this variable in this class and use it whereever you needed it in this class
var selectedItem: cellData?

Related

Getting a EXC_BAD_ACCESS when trying to initialize my custom Cell in TableViewController

My application fetches data from a mock API.
Using a custom cell, I display the names of authors on my landing page viewController.
When I click on a cell, it takes that author's book information to display on a 2nd TableViewController.
But even though the implementation is the same as for the landing page. My app freezes until I get a EXC_BAD_ACCESS error
It seems like it's stuck in an infinite loop, but without a proper error, it's hard to know why.
Infinite Loop?
I can get this to work without using a custom cell, but then I cannot display all the information I want (only book title or release date), so the data is there.
import UIKit
class BooksTableViewCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var pages: UILabel!
#IBOutlet weak var release: UILabel!
// #IBOutlet var coverImage: UIImageView!
static let cellIdentifier = "BooksTableViewCell"
//
override func awakeFromNib() {
super.awakeFromNib()
}
static func nib() -> UINib {
return UINib(nibName: "BooksTableViewCell", bundle: nil)
}
//MARK: configure
public func configure(with viewModel: BooksCellViewModel) {
name.text = viewModel.name
pages.text = String(viewModel.pages)
release.text = viewModel.release
// coverImage.image = viewModel.image
}
}
import UIKit
class BooksTableViewController: UITableViewController {
var books: [Book] = []
var authorName: String = ""
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(BooksTableViewCell.nib(), forCellReuseIdentifier: BooksTableViewCell.cellIdentifier)
tableView.delegate = self
tableView.dataSource = self
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return authorName
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return books.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("Hello1")
let cell = tableView.dequeueReusableCell(withIdentifier: BooksTableViewCell.cellIdentifier, for: indexPath) as! BooksTableViewCell
print("Hello2")
let model = books[indexPath.row]
cell.configure(with: BooksCellViewModel(name: model.title, pages: model.pages, release: model.releaseDate))
return cell
}
}
The landing page controller and cell is similar but works with no problems
import UIKit
class LandingTableViewController: UITableViewController {
let parser = DataAPI()
var authors = [Author]()
var books = [Book]()
var authorName = ""
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(AuthorTableViewCell.nib(), forCellReuseIdentifier: AuthorTableViewCell.cellIdentifier)
tableView.delegate = self
tableView.dataSource = self
parser.getData {
data in
self.authors = data
//Reload UI on Main thread:
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "List of Authors"
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return authors.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: AuthorTableViewCell.cellIdentifier, for: indexPath) as! AuthorTableViewCell
let model = authors[indexPath.row]
cell.configure(with: AuthorCellViewModel(name: model.authorName))
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
books = authors[indexPath.row].books
authorName = authors[indexPath.row].authorName
performSegue(withIdentifier: "Show Books", sender: nil)
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
if (segue.identifier == "Show Books") {
let showBooksViewController: BooksTableViewController = segue.destination as! BooksTableViewController
showBooksViewController.books = books
showBooksViewController.authorName = authorName
}
}
}
I was able to fix the issue by correctly naming my variables. I needed to be using releaseDate not release as per my model object.

UITableView does not populate with data

I am trying to make a simple UITableView with custom cells (including two labels and one image view) but I can't get the table to be populated with data.
I have created the following struct for my data:
struct feed {
var title: String
var subtitle: String
var image: String
}
and here I have defined some sample data:
var myfeed = [feed(title: "Test Feed", subtitle: "Welcome to feedFeed", image: "https://www.demo.com/imnage1.png"), feed(title: "Number 2", subtitle: "Demo?", image: "https://www.demo.com/imnage2.png")]
I have created an UITableView in my Storyboard, have configured the Custom cell and am using the Cell identifier "LabelCell".
I have created a separate cocoaTouchclass file for the UITableViewCell class:
import UIKit
class ehappyTableViewCell: UITableViewCell {
#IBOutlet weak var headlineTitleLabel: UILabel!
#IBOutlet weak var headlineTextLabel: UILabel!
#IBOutlet weak var headlineImageView: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
func tableView(_ tableView: UITableViewCell, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 100.0;//Choose your custom row height
}
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
In my ViewController file I have the following code:
#IBOutlet weak var table: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myfeed.count
}
func tableView(_ tableViwq: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:ehappyTableViewCell = self.table.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) as! ehappyTableViewCell!
let headline = myfeed[indexPath.row]
cell.headlineTitleLabel?.text = headline.title
cell.headlineTextLabel?.text = headline.subtitle
let urlWithoutHTTP = headline.image
let httpAddition = "https:"
let addition = "\(httpAddition)\(urlWithoutHTTP)"
let url = URL(string: addition)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
DispatchQueue.main.async {
cell.headlineImageView.image = UIImage(data: data!)
}
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 140.0;//Choose your custom row height
}
override func viewDidLoad() {
super.viewDidLoad()
self.table.delegate = self
self.table.dataSource = self
}
When I run the app the table will not populate with the sample data I have created.
Any suggestions on what I can do?
If your cell is an xib then you have to register the cell by writing the following code in the viewDidLoad
self.table.register(UINib(nibName: "ehappyTableViewCell", bundle: nil), forCellReuseIdentifier: "LabelCell")
If it is designed inside the viewcontroller in storyboard then no need to register
Check if delegate and dataSource are given
Try replacing the line with following line
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell") as? ehappyTableViewCell

ios swift tableview not showing custom cells

I am trying to create a table view with custom cells from Storyboard layout in an iOS app.
But for some reason the table cells are not being shown. When I tried to set debug breakpoints I found that the debugger is reaching this function
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
but it never reaches this function -
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
Here is my viewcontroller code -
extension NavigationViewController: UITableViewDataSource, UITableViewDelegate, SideMenuControllerDelegate {
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SideMenuTableItem", for: indexPath as IndexPath) as! SideMenuTableItem
cell.setItemData(items[indexPath.row])
return cell
}
public func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func setupTableViews() {
menuTable.register(SideMenuTableItem.self, forCellReuseIdentifier: "SideMenuTableItem")
}
}
class SideMenuTableItem: UITableViewCell {
#IBOutlet weak var menuImage: UIImageView!
#IBOutlet weak var menuLabel: UILabel!
var data: MenuItem?
override func awakeFromNib() {
super.awakeFromNib()
}
func setItemData(_ item: MenuItem) {
data = item
menuLabel.text = data?.title
if data?.icon_res != nil {
menuImage.image = UIImage(named: (data?.icon_res)!)
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
I have checked in the storyboard that I have set the reusable identifier to the table prototype cell and also connected the datasource and the delegate properties to the tableview
and I am calling the setupTableViews() method inside my viewDidLoad() function after creating the items array
But still I am not able to get the cells to appear in my view at all.
Can anyone suggest what am I missing here or what's wrong with my code, or how can I further debug this issue
import UIKit
import SideMenuSwift
class NavigationViewController: UIViewController {
#IBOutlet weak var navigationContainer: UIView!
#IBOutlet weak var emailButton: UIButton!
#IBOutlet weak var phoneButton: UIButton!
#IBOutlet weak var userAvatar: UIImageView!
#IBOutlet weak var userProfile: UIButton!
#IBOutlet weak var userName: UILabel!
#IBOutlet weak var menuTable: UITableView!
var service: AuthenticationService!
var cdc: CoreDataController!
var items: [MenuItem] = []
var currentUser: User?
override func viewDidLoad() {
super.viewDidLoad()
setupSidebar()
initSidebarData()
setupUserHeader()
setupTableViews()
}
func setupUserHeader() {
if currentUser != nil {
if currentUser?.name != nil {
userName.text = currentUser?.name
} else if currentUser?.role != nil {
userName.text = "urTutors " + (currentUser?.role ?? "")
}
if currentUser?.avatarUrl != nil {
userAvatar.downloaded(from: (currentUser?.avatarUrl)!)
}
}
}
func initSidebarData() {
service = AuthenticationServiceProvider()
cdc = CoreDataController()
items = cdc.getNavigationData()
currentUser = cdc.getUserData()
}
func setupSidebar() {
self.view.backgroundColor = UIColor.hexColor("#fff")
navigationContainer.backgroundColor = UIColor.hexColor("#2a2a2a")
SideMenuController.preferences.basic.statusBarBehavior = .hideOnMenu
SideMenuController.preferences.basic.position = .above
SideMenuController.preferences.basic.direction = .left
SideMenuController.preferences.basic.enablePanGesture = true
SideMenuController.preferences.basic.menuWidth = 275
sideMenuController?.delegate = self
}
static func createViewController() -> NavigationViewController {
let sb = UIStoryboard(name: "StudentHomeModuleStoryboard", bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: "NavigationViewController")
return vc as! NavigationViewController
}
}
--UPDATE--
updated setupTableLayout function -
func setupTableViews() {
let bundle = Bundle(for: type(of: self))
let cellNib = UINib(nibName: "SideMenuTableItem", bundle: bundle)
menuTable.register(cellNib, forCellReuseIdentifier: "SideMenuTableItem")
menuTable.register(SideMenuTableItem.self, forCellReuseIdentifier: "SideMenuTableItem")
menuTable.reloadData()
}
After breaking into chat on this, we found that there were two issues.
The first issue was the missing reloadData call mentioned above. That was causing cellForRow to not be called. Adding reloadData corrected that issue, but then the custom cell class's outlets were nil, causing a crash in setItemData.
The second issue was that register(_:forCellReuseIdentifier:) was being called in code, but the custom cell was already setup as part of the Interface Builder UITableView declaration. Calling register again on the custom class re-registered the reuseIdentifier, disconnecting the outlets set up in the storyboard.
Removing the register call and adding reloadData solved all issues.
You are never calling setupTableViews(). You'r code should look like this:
class NavigationViewController: UIViewController, SideMenuControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
setupTableViews()
}
func setupTableViews() {
menuTable.reloadData()
}
}
extension NavigationViewController: UITableViewDataSource, UITableViewDelegate {
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SideMenuTableItem", for: indexPath as IndexPath) as! SideMenuTableItem
cell.setItemData(items[indexPath.row])
return cell
}
public func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
You are never calling the function, nor calling viewDidLoad. This should help. Also, where is the rest of your view controller code (is this all of it? It should not be!).
You don't need to register your cell because you requested it and make sure you reloadData().
Hope this helps!

Table view cell elements not able to click and get data

I have one table view and inside that i placed one main view. And inside that main view i placed one button.And when ever use click on my cell button. I need to get the cell title label.This is what i need. But i tried following below code. Not sure what i am missing out. It not at all calling my cell.add target line.
Code in cell for row at index:
cell.cellBtn.tag = indexPath.row
cell.cellBtn.addTarget(self, action:#selector(self.buttonPressed(_:)), for:.touchUpInside)
#objc func buttonPressed(_ sender: AnyObject) {
print("cell tap")
let button = sender as? UIButton
let cell = button?.superview?.superview as? UITableViewCell
let indexPath = tableView.indexPath(for: cell!)
let currentCell = tableView.cellForRow(at: indexPath!)! as! KMTrainingTableViewCell
print(indexPath?.row)
print(currentCell.cellTitleLabel.text)
}
I even added a breakpoint, still it not at calling my cell.addTarget line
Tried with closure too. In cell for row at index:
cell.tapCallback = {
print(indexPath.row)
}
In my table view cell:
var tapCallback: (() -> Void)?
#IBAction func CellBtndidTap(_ sender: Any) {
print("Right button is tapped")
tapCallback?()
}
Here that print statement is getting print in console.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var list = [String]()
#IBOutlet weak var tableView: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
cell.saveButton.tag = indexPath.row
//cell.saveButton.accessibilityIdentifier = "some unique identifier"
cell.tapCallback = { tag in
print(tag)
}
return cell
}
}
class MyTableViewCell: UITableViewCell {
// MARK: - IBOutlets
#IBOutlet weak var saveButton: UIButton!
// MARK: - IBActions
#IBAction func saveTapped(_ sender: UIButton) {
tapCallback?(sender.tag)
}
// MARK: - Actions
var tapCallback: ((Int) -> Void)?
}
Actually this is not a good programming practice to add the button (which contains in table view cell) target action in view controller. We should follow the protocol oriented approach for it. Please try to under stand the concept.
/*This is my cell Delegate*/
protocol InfoCellDelegate {
func showItem(item:String)
}
/*This is my cell class*/
class InfoCell: UITableViewCell {
//make weak reference to avoid the Retain Cycle
fileprivate weak var delegate: InfoCellDelegate?
//Outlet for views
#IBOutlet var showButton: UIButton?
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
//This is the public binding function which will bind the data & delegate to cell
func bind(with: DataModel?, delegate: InfoCellDelegate?, indexPath: IndexPath) {
//Now the bind the cell with data here
//.....
//Assign the delegate
self.delegate = delegate
}
//Button action
#IBAction func rowSelected(sender: UIButton) {
self.delegate?.showItem(item: "This is coming from cell")
}
}
/*Now in your ViewController you need to just confirm the InfoCellDelegate & call the bind function*/
class ListViewController: UIViewController {
//Views initialisation & other initial process
}
//Table view Delegate & Data source
extension ListViewController: UITableViewDataSource, UITableViewDelegate {
/**
Configure the table views
*/
func configureTable() {
//for item table
self.listTable.register(UINib.init(nibName: "\(InfoCell.classForCoder())", bundle: nil), forCellReuseIdentifier: "\(InfoCell.classForCoder())")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "InfoCell") as! InfoCell
cell.bind(with: DataModel, delegate: self, indexPath: indexPath)
return cell
}
}
extension ListViewController: InfoCellDelegate {
func showItem(item) {
print(item)
}
}

Passing coredata from tableview to another tableview

I am struggling with getting my care data to populate my second tableview controller. The data is populating the first tableview and I can select a row and the segue is used to go to the second table but the labels are not populated.
I've looked all over and have found older samples or obj-c but I cannot figure it out, so any help pointing this n00b in the right direction will be helpful.
Here is what I have, I think I am missing how to populate a variable to pass in prepareForSegue in the list tableview, but I could be wrong. I get a warning error in that function (Warning cannot assign value of type 'ListEntity' to type '[ListEntity]').
CoreData
Entity = ListEntity
Attributes = title, event & location (all as Strings)
listTableViewController
import UIKit
import CoreData
class ListTableViewController: UITableViewController {
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var lists = [ListEntity]()
override func viewDidLoad() {
super.viewDidLoad()
self.title = "The List"
let addButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: self, action: #selector(ListTableViewController.addButtonMethod))
navigationItem.rightBarButtonItem = addButton
}
func addButtonMethod() {
print("Perform action")
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
reloadData()
tableView.reloadData()
}
func reloadData() {
let fetchRequest = NSFetchRequest(entityName: "ListEntity")
do {
if let results = try managedObjectContext.executeFetchRequest(fetchRequest) as? [ListEntity] {
lists = results
}
} catch {
fatalError("There was an error fetching the list!")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lists.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ListCell") as! ListTableViewCell
let list = lists[indexPath.row]
cell.configurationWithSetup(list)
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("DetailsSegue", sender: self)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetailsSegue" {
let destinationVC = segue.destinationViewController as! DetailsTableViewController
let indexPath : NSIndexPath = self.tableView.indexPathForSelectedRow!
print(indexPath.row) // Print the Row selected to console
// Place the code to pass data here?
// destinationVC.lists = lists[indexPath.row]
// Warning cannot assign value of type 'ListEntity' to type '[ListEntity]'
}
}
}
listTableViewCell
import UIKit
class ListTableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
func configurationWithSetup(list: AnyObject) {
titleLabel.text = list.valueForKey("title") as! String?
}
}
detailsTableViewController
import UIKit
import CoreData
class DetailsTableViewController: UITableViewController {
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var lists = [ListEntity]()
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("DataCell") as! DetailsTableViewCell
let list = lists[indexPath.row]
cell.configurationWithSetup(list)
return cell
}
}
detailsTableViewCell
import UIKit
import CoreData
class DetailsTableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var eventLabel: UILabel!
#IBOutlet weak var locationLabel: UILabel!
func configurationWithSetup(list: AnyObject) {
titleLabel.text = list.valueForKey("title") as! String?
eventLabel.text = list.valueForKey("event") as! String?
locationLabel.text = list.valueForKey("location") as! String?
}
}
The warning contains the answer - just change
var lists = [ListEntity]() to
var lists = ListEntity(), or var lists:ListEntity! and when you prepare for segue set that value.
Then you will need to change
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("DataCell") as! DetailsTableViewCell
// as data source is not array you can just you the item you passed
// let list = lists[indexPath.row]
cell.configurationWithSetup(lists)
return cell
}
You should use a static table view if you just want one cell
More info per you current issue
class DetailsTableViewController: UITableViewController {
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var theDetailListEntity:ListEntity!
override func viewDidLoad() {
super.viewDidLoad()
print(theDetailListEntity) // check that you passed it across
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("DataCell") as! DetailsTableViewCell
cell.configurationWithSetup(theDetailListEntity)
return cell
}
}
Don't forget to add prepare for segue in the listTableViewController otherwise theDetailListEntity won't be set... and then it will crash.
Depending on how you set up your segue, it may differ. But this is what you need
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("showMyDetailView", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showMyDetailView" {
guard let
vc = segue.destinationViewController as? DetailsTableViewController,
ip = sender as? NSIndexPath else { fatalError() }
let item = lists[ip.row]
vc.theDetailListEntity = item
// set the item in the next VC
tableView.deselectRowAtIndexPath(ip, animated: true)
}
}

Resources