Fail to display the custom cell file in my TableView? - ios

Iv made a NIB custom cell file but I fail to display the custom cell file in my tableView at all. The code is error free and runs but I'm struggling to display the Custom Cell. I Initially thought my problem was from the Unwind Segue that I created to pass the data from the InputScreen to the ViewController but I'm just not sure what the issue could be at this point?
Any help what's so ever would be much appreciated.
MAIN VIEWCONTROLLER
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var IzParcelz = [IzParcel]()
override func viewDidLoad() {
super.viewDidLoad()
let nib = UINib(nibName: "IzparcelCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "IzparcelCell")
tableView.delegate = self
tableView.dataSource = self
}
// MARK: - TableView data source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return IzParcelz.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "IzparcelCell", for: indexPath) as! IzparcelCell
let izPackage = IzParcelz[indexPath.row]
cell.nameLabel.text = izPackage.name
cell.addressLabel.text = izPackage.address
cell.trackingNumLabel.text = izPackage.trackingNumber
return cell
}
// MARK: - TableView Delegate
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
IzParcelz.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
IzParcel.saveIzParcel(IzParcelz)
}
}
#IBAction func prepareForUnwind(segue: UIStoryboardSegue) {
guard segue.identifier == "saveUnwind" else { return }
let sourceViewController = segue.source as! InputViewController
if let P = sourceViewController.izParcel {
if let selectedIndexPath = tableView.indexPathForSelectedRow {
IzParcelz[selectedIndexPath.row] = P
tableView.reloadRows(at: [selectedIndexPath], with: .none)
} else {
let newIndexPath = IndexPath(row: IzParcelz.count, section: 0)
IzParcelz.append(P)
tableView.insertRows(at: [newIndexPath], with: .automatic)
}
}
IzParcel.saveIzParcel(IzParcelz)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetails" {
let izViewController = segue.destination as! InputViewController
let indexPath = tableView.indexPathForSelectedRow!
let selectedTodo = IzParcelz[indexPath.row]
izViewController.izParcel = selectedTodo
}
}
}
INPUT VIEWCONTROLLER
import UIKit
class InputViewController: UITableViewController {
var izParcel: IzParcel?
#IBOutlet weak var statusTextLabel: UITextField!
#IBOutlet weak var nameTextLabel: UITextField!
#IBOutlet weak var addressTextLabel: UITextField!
#IBOutlet weak var trackingNumTextLabel: UITextField!
#IBOutlet weak var notesTextLabel: UITextField!
#IBOutlet weak var statusUpdateTextLabel: UIDatePicker!
#IBOutlet weak var dateAndTimeTextLabel: UIDatePicker!
#IBOutlet weak var saveButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if let izParcels = izParcel {
nameTextLabel.text = izParcels.name
addressTextLabel.text = izParcels.address
trackingNumTextLabel.text = izParcels.trackingNumber
notesTextLabel.text = izParcels.notes
dateAndTimeTextLabel.date = izParcels.dateAndTime
statusUpdateTextLabel.date = izParcels.statusUpdated
}
}
#IBAction func deleteButton(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
#IBAction func saveButton(_ sender: UIButton) {
print("PressedButtttonnnnTesst")
self.performSegue(withIdentifier: "saveUnwind", sender: self)
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "saveUnwind" else { return }
let name = nameTextLabel.text!
let address = addressTextLabel.text!
let trackingNumber = trackingNumTextLabel.text!
let notes = notesTextLabel.text!
let dates = dateAndTimeTextLabel.date
let statusUpdate = statusUpdateTextLabel.datePickerMode
izParcel = IzParcel(name: name, address: address, trackingNumber: trackingNumber, notes: notes, dateAndTime: dates, statusUpdated: dates)
}
}
IZPARCEL CELL
import UIKit
class IzparcelCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var addressLabel: UILabel!
#IBOutlet weak var trackingNumLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
[]

All the code I had was correct except for the order of the code. After reviewing and reallocating the prepare for segue declaration that was inside the saveButton Action to just outside it. I was able to pass the data from the InputScreen to the Custom TableView Cell in the TableView on the mainScreen.

Related

Is there a simple way to delete specific custom cells from a UITableView?

I am trying to instantiate empty Buyer cells (custom cell) in my table view and then have the user populate the buyers' names. When the user presses the delete button for a row/cell, it should delete the corresponding row/cell regardless of whether or not the textfield for that row has been populated or not. Clearly, I am not getting the desired behavior. For example, when I press delete Row0 (whose textfield says "Buyer 0") and the tableview reloads, Buyer 0 is still there, but one of the empty Buyer cells at the end gets deleted instead.
import UIKit
class EntryAlertViewController: UIViewController {
//Fields/Table
#IBOutlet weak var itemField: UITextField!
#IBOutlet weak var priceField: UITextField!
#IBOutlet weak var tableView: UITableView!
//Visual Components
#IBOutlet weak var mainView: UIView!
#IBOutlet weak var titleView: UIView!
#IBOutlet weak var splitItemButton: UIButton!
#IBOutlet weak var cancelButton: UIButton!
#IBOutlet weak var addItemButton: UIButton!
//Commonly Used Objects/Variables
var potentialBuyers: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
potentialBuyers.append("")
tableView.dataSource = self
tableView.register(UINib(nibName: "BuyerCell", bundle: nil), forCellReuseIdentifier: "ReusableCell")
}
override func viewWillAppear(_ animated: Bool) {
}
#IBAction func splitItemPressed(_ sender: UIButton) {
potentialBuyers.append("")
tableView.reloadData()
}
}
Here are the tableview datasource and the delete button delegate.
extension EntryAlertViewController: UITableViewDataSource, DeleteButtonDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return potentialBuyers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! BuyerCell
cell.deleteButtonDelegate = self
cell.indexPath = indexPath
cell.nameField.text = cell.buyerName
if potentialBuyers.count == 1 {
cell.deleteButton.isHidden = true
} else {
cell.deleteButton.isHidden = false
}
return cell
}
func deletePressed(index: Int) {
potentialBuyers.remove(at: index)
tableView.reloadData()
}
}
And here is my BuyerCell class with the UITextFieldDelegate as an extension.
import UIKit
protocol DeleteButtonDelegate {
func deletePressed(index: Int)
}
class BuyerCell: UITableViewCell {
#IBOutlet weak var deleteButton: UIButton!
#IBOutlet weak var nameField: UITextField!
var deleteButtonDelegate: DeleteButtonDelegate!
var indexPath: IndexPath!
var buyerName: String?
override func awakeFromNib() {
super.awakeFromNib()
self.nameField.delegate = self
}
#IBAction func deletePressed(_ sender: UIButton) {
//print the indexPath.row that this was pressed for
print("delet pressed for \(indexPath.row)")
self.deleteButtonDelegate?.deletePressed(index: indexPath.row)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension BuyerCell: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
print("textFieldDidBeginEditing")
buyerName = nameField.text
}
func textFieldDidEndEditing(_ textField: UITextField) {
print("textFieldDidEndEditing")
buyerName = nameField.text
}
}
Your problem is in this line
cell.nameField.text = cell.buyerName
Cells are reused from a reuse pool, so you can't rely on the cell holding any particular state or value.
Your buyer name needs to come from your data model array.
Something like
cell.nameField.text = self.potentialBuyers[indexPath.row]
Reloading the whole tableview is a bit excessive when you have only deleted a single row; Just delete the relevant row.
You can also clean up your delegation protocol so that there is no need for the cell to track its indexPath -
protocol DeleteButtonDelegate {
func deletePressed(in cell: UITableViewCell)
}
In your cell:
#IBAction func deletePressed(_ sender: UIButton) {
self.deleteButtonDelegate?.deletePressed(in: self)
}
In your view controller:
func deletePressed(in cell: UITableViewCell) {
guard let indexPath = tableView.indexPath(for: cell) else {
return
}
potentialBuyers.remove(at: indexPath.row)
tableView.deleteRows(at:[indexPath], with: .automatic)
}
There is a major issue in your code. You are not updating the data model so the changes in the cells are lost when the user scrolls.
Rather then quite objective-c-ish protocol/delegate in Swift callback closures are much more convenient and efficient. You can use one callback for both updating the model and deleting the cell.
Replace the BuyerCell cell with
class BuyerCell: UITableViewCell {
#IBOutlet weak var deleteButton: UIButton!
#IBOutlet weak var nameField: UITextField!
var callback : ((UITableViewCell, String?) -> Void)?
override func awakeFromNib() {
super.awakeFromNib()
self.nameField.delegate = self
}
#IBAction func deletePressed(_ sender: UIButton) {
callback?(self, nil)
}
}
extension BuyerCell: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
print("textFieldDidBeginEditing")
callback?(self, nameField.text)
}
func textFieldDidEndEditing(_ textField: UITextField) {
print("textFieldDidEndEditing")
callback?(self, nameField.text)
}
}
In the controller in cellForRow assign the callback and handle the actions. The actions work also reliably if cells are reordered, inserted or deleted.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! BuyerCell
let buyerName = potentialBuyers[indexPath.row]
cell.nameField.text = buyerName
cell.callback = { [unowned self] cCell, cName in
let currentIndexPath = tableView.indexPath(for: cCell)!
if let name = cName {
self.potentialBuyers[currentIndexPath.row] = name
} else {
self.potentialBuyers.remove(at: currentIndexPath.row)
tableView.deleteRows(at: [currentIndexPath], with: .fade)
}
}
cell.deleteButton.isHidden = potentialBuyers.count == 1
return cell
}

Updating Label in Cell

I have a TableView which rows contain label and two buttons. What I wanna do is that when a user clicks the first button "Set Name", a pop up view comes up in which he can input text from keyboard. After hitting "Set", pop up view is dismissed and label inside a row containing the clicked button changes to the input text. I set the delegates but I cannot make label to change.
TableView:
import UIKit
class SetGame: UIViewController, UITableViewDelegate, UITableViewDataSource
{
var numOfPlayers = Int()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return numOfPlayers
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.Name.text = "Player \(indexPath.row + 1)"
cell.btn1.tag = indexPath.row
cell.btn2.tag = indexPath.row
return cell
}
override func viewDidLoad()
{
super.viewDidLoad()
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.none
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
#IBAction func setName(sender: UIButton)
{
let thisVC = storyboard?.instantiateViewController(withIdentifier: "SetName") as! SetName
thisVC.delegate = self
present(thisVC, animated: true, completion: nil)
}
#IBAction func setFingerprint(_ sender: UIButton)
{
}
#IBAction func unwindToSetGame(_ segue: UIStoryboardSegue)
{
print("unwinded to SetGame")
}
#IBOutlet weak var tableView: UITableView!
}
extension SetGame: nameDelegate
{
func named(name: String)
{
let indexP = IndexPath(row: 0, section: 0)
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexP) as! TableViewCell
cell.Name.text = "bkjhvghcjhkv"
//wanted to see if it changes first cell. But doesn't work
}
}
TableViewCell Class:
import UIKit
class TableViewCell: UITableViewCell
{
override func awakeFromNib()
{
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
#IBOutlet weak var Name: UILabel!
#IBOutlet weak var btn1: UIButton!
#IBOutlet weak var btn2: UIButton!
}
Pop up View:
import UIKit
protocol nameDelegate
{
func named(name: String)
}
class SetName: UIViewController
{
var delegate: nameDelegate!
override func viewDidLoad()
{
super.viewDidLoad()
window.layer.borderWidth = 1
window.layer.borderColor = UIColor.white.cgColor
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
#IBAction func closePopUp(_ sender: Any)
{
if input.text != ""
{
delegate.named(name: input.text!)
}
dismiss(animated: true, completion: nil)
}
#IBOutlet weak var input: UITextField!
#IBOutlet weak var window: UIView!
}
Replace this
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexP) as! TableViewCell
with
let cell = tableView.cellForRow(at:indexP) as! TableViewCell

TableView Cell actions

I have a ViewController, with a list of data from a son file. This page run perfectly. On this page are many pub's with prices. And I want to make another scene (SecondViewController). And every time, when I push a pub from the list I want to display on another scene more information about that place. That run, but when I choose a pub the program shows the information about the first pub from the list, and when I choose another he shows the previous pub, which I choose before. And sorry my english is very bad. Please help me :D
Here is my ViewController:
import UIKit
var nev: [String] = []
var cim: [String] = []
var ar: [String] = []
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var myIndex: Int?
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "pubok", withExtension: "json")
do {
let allContactsData = try Data(contentsOf: url!)
let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
if let arrJSON = allContacts["Pubok"] {
for index in 0...arrJSON.count-1 {
let aObject = arrJSON[index] as! [String : AnyObject]
nev.append(aObject["Hely neve"] as! String)
cim.append(aObject["Cím"] as! String)
ar.append(aObject["Legolcsóbb sör"] as! String)
}
}
self.tableView.reloadData()
}
catch {
}
}
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 nev.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.nevLabel.text = nev[indexPath.row]
cell.arLabel.text = ar[indexPath.row] + "/0.5l"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
myIndex = indexPath.row
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! SecondViewController
vc.myIndex = myIndex
}
}
Here is my SecondViewController:
import UIKit
class SecondViewController: UIViewController {
myIndex: Int?
#IBOutlet weak var secondnevLabel: UILabel!
#IBOutlet weak var secondcimLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
secondnevLabel.text = nev[myIndex!]
secondcimLabel.text = cim[myIndex!]
}
}
And this is the TableViewCell:
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var nevLabel: UILabel!
#IBOutlet weak var arLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
Instead of having the global variable myIndex, have a local variable in the second view controller. Use prepare(for segue:) in the first view controller to assign the selected row index to that variable.
ViewController:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
// etc
}
// Remove didSelectRowAt
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let row = (self.tableView.indexPathForSelectedRow as NSIndexPath?)?.row
let vc = segue.destination as! SecondViewController
vc.myIndex = row
}
SecondViewController:
class SecondViewController: UIViewController {
var myIndex: Int?
#IBOutlet weak var secondnevLabel: UILabel!
#IBOutlet weak var secondcimLabel: UILabel!
// etc

How can I pass one just one part of a struct?

I'm trying to pass just the image part of a struct (containing also two textFields, and another imageView I'd like to not pass).
Here is the tableViewController
import UIKit
class SentMemesTableViewController: UITableViewController {
var _tableView: UITableView!
var memeData: [Meme] = []
//calling memes from array in Delegate
let appDelegate = UIApplication.shared.delegate as! AppDelegate
var memes: [Meme] {
return appDelegate.memes
}
override func viewWillAppear(_ animated: Bool) {
tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.isScrollEnabled = true
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MemeDetailViewController" ,
let nextScene = segue.destination as? MemeDetailViewController ,
let indexPath = tableView.indexPathForSelectedRow {
let selectedMeme = memes[indexPath.row].memedImage
nextScene.sentMemeView.image = Meme.memedImage
}
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//navigationController!.pushViewController(MemeDetailViewController, animated: true)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return memes.count
}
// Here it is! -----
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let tableViewCell = tableView.dequeueReusableCell(withIdentifier: "sentMemesTableView") as! MemeTableViewCell
let meme = memes[indexPath.row]
tableViewCell.tableViewImage.image = meme.memedImage
tableViewCell.tableViewLabel.text = "\(meme.topText)...\(meme.bottomText)"
return tableViewCell
}
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return false
}
func deleteMemesInTableViewCell(_ index: Int) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.memes.remove(at: index)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == UITableViewCellEditingStyle.delete) {
tableView.beginUpdates()
deleteMemesInTableViewCell(indexPath.row)
tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.left)
tableView.endUpdates()
}
}
}
Here is the Meme and SentMemeView structs.
import Foundation
import UIKit
struct Meme {
let topText: String
let bottomText: String
let originalImage: UIImage
let memedImage: UIImage
}
struct SentMemeImageView {
var memedImageDetailVC: UIImageView
}
I can't find a way to call it successfully.
Here is the MemeDetailViewController. I need just for the sentMemeView to display the SentMemeImageView.
class MemeDetailViewController: UIViewController {
var meme = SentMemeImageView?.self
#IBOutlet weak var sentMemesBtn: UIBarButtonItem!
#IBOutlet weak var editBtn: UIBarButtonItem!
#IBOutlet weak var sentMemeView: UIImageView!
func displayMeme(_ meme: SentMemeImageView) {
}
#IBAction func launchMemeEditorViewController(_ sender: Any) {
_ = navigationController?.popViewController(animated: true)
}
//unwinding to the view before (the collectionView, or the tableView)
#IBAction func unwindVC(for unwindSegue: UIStoryboardSegue, towardsViewController subsequentVC: UIViewController) {
self.dismiss(animated: true, completion: nil)
}
}
First of all, sad to say that, your code is quite messed up:
You have with three different kinds of data sources, some are ignored, some you work with, but not in a consistent way:
data from the app delegate (deletion of data)
memeData property (display of data)
memes property (ignored)
You should really focus on where the data is stored and how to access it.
Secondly, you won't send views from one view controller to the other, but data. So rather use UIImage than UIImageView. So you'll hand in a SentMemeImage to the details controller.
I tried to clean up the code a little, but just to answer your explicit question. Please refactor it!
struct Meme {
let topText: String
let bottomText: String
let originalImage: UIImage
let memedImage: UIImage
}
struct SentMemeImage {
var memedImage: UIImage
}
class SentMemesTableViewController: UITableViewController {
var memeData: [Meme] = []
// ----8<---- snipp ----8<----
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MemeDetailViewController" ,
let nextScene = segue.destination as? MemeDetailViewController ,
let indexPath = tableView.indexPathForSelectedRow {
let selectedMeme = memeData[indexPath.row]
let sentMemeImage = SentMemeImage(memedImage: selectedMeme.memedImage)
nextScene.meme = sentMemeImage
}
}
// ----8<---- snipp ----8<----
}
class MemeDetailViewController: UIViewController {
var meme:SentMemeImage?
#IBOutlet weak var sentMemesBtn: UIBarButtonItem!
#IBOutlet weak var editBtn: UIBarButtonItem!
#IBOutlet weak var sentMemeView: UIImageView!
func displayMeme() {
self.sentMemeView.image = self.meme?.memedImage
}
}

Pass core data from selected table cell to new view controller

I'm trying to pass data (title, ingredients, steps, image) from the selected table cell to a new view controller. But I don't know how to do that. I got lots of errors, so now I'm starting again. Can anyone help me? I'm new to coding. Thanks:-) My code:
VIEWCONTROLLER.SWIFT
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var recipes = [Recipe]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func viewDidAppear(animated: Bool) {
fetchAndSetResults()
tableView.reloadData()
}
func fetchAndSetResults(){
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Recipe")
do {
let results = try context.executeFetchRequest(fetchRequest)
self.recipes = results as! [Recipe]
} catch let err as NSError {
print(err.debugDescription)
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("RecipeCell") as? RecipeCell {
let recipe = recipes[indexPath.row]
cell.configureCell(recipe)
return cell
} else {
return RecipeCell()
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return recipes.count
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "RecipeDetail") {
//I WANT TO PASS THE DATA FROM THE TABLE CELL TO THE NEW VIEW CONTROLLER (RECIPEDETAILVC)
}
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
context.deleteObject(recipes[indexPath.row])
app.saveContext()
recipes.removeAtIndex(indexPath.row)
tableView.reloadData()
}
}
}
CREATERECIPE.SWIFT
class CreateRecipeVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var recipeTitle: UITextField!
#IBOutlet weak var recipeIngredients: UITextField!
#IBOutlet weak var recipeSteps: UITextField!
#IBOutlet weak var recipeImage: UIImageView!
#IBOutlet weak var addRecipeBtn: UIButton!
var imagePicker: UIImagePickerController!
override func viewDidLoad() {
super.viewDidLoad()
imagePicker = UIImagePickerController()
imagePicker.delegate = self
recipeImage.layer.cornerRadius = 5.0
recipeImage.clipsToBounds = true
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
imagePicker.dismissViewControllerAnimated(true, completion: nil)
recipeImage.image = image
}
#IBAction func addImage(sender: AnyObject!) {
presentViewController(imagePicker, animated: true, completion: nil)
}
#IBAction func createRecipe(sender: AnyObject!) {
if let title = recipeTitle.text where title != "" {
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let entity = NSEntityDescription.entityForName("Recipe", inManagedObjectContext: context)!
let recipe = Recipe(entity: entity, insertIntoManagedObjectContext: context)
recipe.title = title
recipe.ingredients = recipeIngredients.text
recipe.steps = recipeSteps.text
recipe.setRecipeImage(recipeImage.image!)
context.insertObject(recipe)
do {
try context.save()
} catch {
print("Could not save recipe")
}
self.navigationController?.popViewControllerAnimated(true)
}
}
}
RECIPEDETAILVC.SWIFT
import UIKit
import CoreData
class RecipeDetailVC: UIViewController {
#IBOutlet weak var recipeImage: UIImageView!
#IBOutlet weak var recipeTitle: UILabel!
#IBOutlet weak var recipeIngredients: UILabel!
#IBOutlet weak var recipeSteps: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//I WANT TO DISPLAY THE CORE DATA INFORMATION FROM THE TABLE CELL I SELECTED.
}
}
RECIPECELL.SWIFT
class RecipeCell: UITableViewCell {
#IBOutlet weak var recipeTitle: UILabel!
#IBOutlet weak var recipeImage: UIImageView!
func configureCell(recipe: Recipe) {
recipeTitle.text = recipe.title
recipeImage.image = recipe.getRecipeImage()
}
}
You need to track which item the person clicked.
var mySelection: Int?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
mySelection = indexPath.row
}
Then, use that when doing the segue.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "RecipeDetail") {
//I WANT TO PASS THE DATA FROM THE TABLE CELL TO THE NEW VIEW CONTROLLER (RECIPEDETAILVC)
let recipeDetailControler = segue.destinationViewController as! RecipeDetailViewController
if let mySelection = mySelection {
let recipe = recipes[mySelection]
// add this function to your
recipeDetailControler.configureRecipeData(recipe)
}
}
}
Add this function to RecipeDetailViewController:
func configureRecipeData(recipe: Recipe) {
// IMPLEMENT ME
}

Resources