How to select cell image in CollectionView then segue to ViewController - swift

I have looked up many examples and tried to incorporate but have been unsuccessful. In my CollectionView (That has been placed in a ViewController), I'd like to select a cell and push the cell image to another ViewController. The references to images have been placed in an Array of Dictionaries within a plist file. I'm not sure, how i should edit both my prepareForSegue or my func collectionView...didSelectItemAtIndexPath. Also, any detailed explanation to go along with your code will be helpful as I'm still learning swift and its syntax.
Below is what i think all the information you need but please let me know if you need more:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "ShowToStory") {
var story = sender as! UICollectionViewCell, indexPath = collectionView.indexPathForCell(story)
}
}
private func initStoryImages() {
var storyArchives = [StoryImages]()
let inputFile = NSBundle.mainBundle().pathForResource("StoryArchive", ofType: "plist")
let inputDataArray = NSArray(contentsOfFile: inputFile!)
for inputItem in inputDataArray as! [Dictionary<String, String>] {
let storyImage = StoryImages(dataDictionary: inputItem)
storyArchives.append(storyImage)
}
storyImages = storyArchives
}
ADDITIONAL CLASS: CollectionViewCell class
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var cellImage: UIImageView!
func setStoryImage(item:StoryImages){
cellImage.image = UIImage(named:item.itemImage)
}
}
ADDITIONAL CLASS: UIViewController (Edit_1)
class StoryView: UIViewController{
#IBOutlet weak var ImageToStory: UIImageView!
var story: Story?
override func viewWillAppear(animated: Bool) {
if let story = story {
ImageToStory.image = UIImage(named: story.imageName)
}
}
}

Your story view should have public setter for story image. Then You can use prepareForSegue method to pass data. If You still have problems consider watching some videos from Stanford University iOS programming lecture on iTunes U, it is free and this topic is widely covered there.

Related

Parsing data from a collectionview Cell to a new viewController using a button in the CollectionViewCell

I have a collectionView that I am populating using an array I created in a class. The collectionView works but the problem is when I want to segue to another viewController using a button in the collectionViewCell as well as parsing specific data from that cell to the viewController.
An example of what I am trying to do is if I press the button in the cell for the question image I want to segue to the next viewController and I want that viewController's image to be the question image, and maybe i the future add some other data corresponding to it.
I have looked at the other answers on this site and other sites, which got me this far, but there is nothing that I can find to fix this problem for a collectionView. I know that it is similar to a tableView, but when I try and change it based on a tableView, but it doesn't seem to work for me.
This is the image of what the first and second views look like
This is the class i created:
import Foundation
import UIKit
class Information {
var image = ""
var button = ""
var infoOne = ""
var infoTwo = ""
var price = ""
init(image: String, button: String, infoOne: String, infoTwo: String, price: String) {
self.image = image
self.button = button
self.infoOne = infoOne
self.infoTwo = infoTwo
self.price = price
}
//MARK: Carousel Data
static func createData() -> [Information] {
return [
Information(image: "question", button: "Buy One", infoOne: "First Data", infoTwo: "Second Data", price: "10"),
Information(image: "exclamation", button: "Buy Two", infoOne: "First Data", infoTwo: "Second Data", price: "20"),
Information(image: "period", button: "Buy Three", infoOne: "First Data", infoTwo: "Second Data", price: "30"),
Information(image: "all", button: "Buy Four", infoOne: "First Data", infoTwo: "Second Data", price: "40")
]
}
}
This array works just fine when it populates the collectionViewCell.
This is the collectionViewCell
import UIKit
class InfoCollectionViewCell: UICollectionViewCell {
var infomation: Information! {
didSet {
updateUI()
}
}
var addBtnAction : (()-> ())?
#IBOutlet weak var infoImage: UIImageView!
#IBOutlet weak var infoLblOne: UILabel!
#IBOutlet weak var infoLblTwo: UILabel!
#IBOutlet weak var priceLbl: UILabel!
#IBOutlet weak var buyBtn: UIButton!
fileprivate func updateUI() {
infoImage.image! = UIImage(named: infomation.image)!
infoLblOne.text = infomation.infoOne
infoLblTwo.text = infomation.infoTwo
priceLbl.text = infomation.price
buyBtn.setTitle(infomation.button, for: .normal)
}
#IBAction func buyBtnPressed(_ sender: Any) {
print("INFORMATION: \(infomation.image)")
addBtnAction?()
}
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = 5.0
self.clipsToBounds = true
}
}
this is the viewController:
import UIKit
class ViewController: UIViewController {
let collectionViewCellId: String = "carouselCollectionCell"
#IBOutlet weak var collectionView: UICollectionView!
fileprivate var information = Information.createData()
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.delegate = self
}
}
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return information.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "infoCell", for: indexPath) as! InfoCollectionViewCell
cell.addBtnAction = {
self.performSegue(withIdentifier: "mainSegue", sender: self)
}
cell.infomation = self.information[indexPath.item]
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mainSegue" {
let nxtVC = segue.destination as? DetailViewController
let cell = sender as! InfoCollectionViewCell
let myIndexPath = self.collectionView.indexPath(for: cell)
nxtVC?.infomation = information[(myIndexPath?.item)!]
}
}
}
So when I run the app everything is fine until I press the button to segue and parse data. The app crashes and this is what it is saying is the cause:
This is what is in the output console:
Could not cast value of type 'carousel.ViewController' (0x107992178) to 'carousel.InfoCollectionViewCell' (0x107991f98).
2018-09-28 21:22:52.116698-0400 carousel[1573:38999] Could not cast value of type 'carousel.ViewController' (0x107992178) to 'carousel.InfoCollectionViewCell' (0x107991f98).
(lldb)
I would prefer to keep the button if at all possible, but if it is not possible I will change that. I am not sure what it is that I am doing wrong. If there is anything else that I can help with please let me know. Thank you very much.
EDIT:
It seems that I forgot to include one of the important views, the one for the other viewController that is segued to.
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
this is the view that i segue to:
import UIKit
class DetailViewController: UIViewController {
#IBOutlet weak var infoImage: UIImageView!
#IBOutlet weak var dataTxtView: UITextView!
var testingImage: UIImage = UIImage()
var infomation: Information! {
didSet {
updateUI()
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
fileprivate func updateUI() {
let images = UIImage(named: infomation.image)
infoImage.image = images
print("Image: \(infomation.image)")
}
}
In the updateUI function I tried to make the infoImage the same as infomation.image but it crashes and states:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
This doesn't make much sense to me because I tried to print what the string of infomation.image is, and it worked, but the moment I try and put it as an image it seems to crash.
Thank you again
EDIT2:
I figured out what I was doing wrong. It seems that I was always trying to use an optional string. How i fixed it is that I changed the class I made and instead of a string and turn that into an image it is already an image. I also tried to create an if let statement to remove the optional.
This is what the prepareForSegue looks like in the main ViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mainSegue" {
let nxtVC = segue.destination as? DetailViewController
let cell = sender as? InfoCollectionViewCell
let myIndexPath = self.collectionView.indexPath(for: cell!)
if let indexPath = myIndexPath {
nxtVC?.infomation = information[indexPath.row]
}
}
}
this is what the viewDidLoad looks like:
override func viewDidLoad() {
super.viewDidLoad()
print("***********TESTINGIMAGE: \(infomation.image!)***********")
infoImage.image = infomation.image!
}
I know that I am unwrapping the image with an ! but i don't know how to remove the optional otherwise.
Thank you for the Help.
The problem is that you are assuming that the sender in prepare is an instance of the cell but your call to performSegue is passing self as the sender. But self in that case is the view controller, not the cell.
The solution is to pass the cell instead of self.
cell.addBtnAction = {
self.performSegue(withIdentifier: "mainSegue", sender: cell)
}

Trouble with segue/unsegue when making a list app

I'm new to coding, so please bear with me. I was following an online tutorial that worked with plists to make a habit list app. I have a table view controller that shows a list of habits and a segue that presents modally a view controller that has text fields to add a habit.
enter image description here
Every time it runs, nothing happens when I click on the "save" and "cancel" buttons. I realize this is a vague question as it doesn't pinpoint to a specific issue, but I am really struggling with fixing this issue and would really appreciate if someone proofreads the code. The app builds and runs with no warnings.
This is the table view controller that shows the habits:
class TableViewController: UITableViewController {
//MARK: Properties
var habits = [Habit]()
//MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return habits.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") else {
fatalError("The dequeued cell is not an instance of ViewController.")
}
// Fetches the appropriate habit for the data source layout.
let habit = habits[indexPath.row]
cell.textLabel?.text = habit.mainGoal
cell.detailTextLabel?.text = habit.microGoal
return cell
}
#IBAction func unwindToHabitList(sender: UIStoryboardSegue) {
if let source = sender.source as?ViewController, let habit = source.habit {
//add a new habit
let newIndexPath = IndexPath(row: habits.count, section: 0)
habits.append(habit)
tableView.insertRows(at: [newIndexPath], with: .automatic)
}
}
This is the view controller that adds a habit:
class ViewController: UIViewController, UITextFieldDelegate, UINavigationControllerDelegate {
#IBOutlet weak var saveButton: UIBarButtonItem!
#IBOutlet weak var mainGoalTextField: UITextField!
#IBOutlet weak var microGoalTextField: UITextField!
var habit: Habit?
//method for configuring controller before presenting
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
//configure this destination view controller only when save button is pressed
guard let button = sender as? UIBarButtonItem, button === saveButton else {
os_log("save button was not pressed, cancelling", log: OSLog.default, type: .debug)
return
}
let mainGoal = mainGoalTextField.text ?? ""
let microGoal = microGoalTextField.text ?? ""
//set the habit to be passed on to tableViewController after the unwind segue
habit = Habit(mainGoal: mainGoal, microGoal: microGoal)
}
#IBAction func cancel(_ sender: UIBarButtonItem) {
// Depending on style of presentation (modal or push presentation), this view controller needs to be dismissed in two different ways.
let isPresentingInAddHabitMode = presentingViewController is UINavigationController
if isPresentingInAddHabitMode {
dismiss(animated: true, completion: nil)
}
else if let owningNavigationController = navigationController{
owningNavigationController.popViewController(animated: true)
}
else {
fatalError("The ViewController is not inside a navigation controller.")
}
}
I appreciate any and all help in advance!
STORYBOARD CONNECTIONS:
TABLEVIEW CONTROLLER CONNECTIONS
ADD HABIT VIEW CONTROLLER CONNECTIONS

Passing a variable from a customCell.xib's button to another UIViewController

My custom cell has a button that when clicked, the user can be taken to another ViewControler. That button has a titleLabel with the String of a user id. What I want to do is take the user to a new UIViewController, passing that clicked buttons's titleLabel (user id) to a variable on the new View Controller. That way, I can use that variable (user id) get further information from firebase and display it on the UI View controller.
on the .xib of the custom cell, I print the UID to make sure each button prints with the correspondent ID, which it does. I can't figure out a way to pass that ID to a new ViewController.
I tried researching online and I found out you can't do prepare(for segue) or performsegue(WithIdentifier) on a customCell.xib.
I tried doing delegates and then protocols but still couldn't get it to work. I am new with Swift. Any help would be great, thank you!
This is the customCell.Xib's Swift file:
class CustomCellTableViewCell: UITableViewCell {
#IBOutlet weak var postImage: UIImageView!
#IBOutlet weak var nameLbl: UILabel!
#IBOutlet weak var descriptionLbl: UITextView!
#IBOutlet weak var profileImageBtn: UIButton!
#IBOutlet weak var profileImage: UIImageView!
#IBOutlet weak var view: UIView!
var btnSelected : Bool = false
var vcInstance: ProfilesTableVC?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
view.clipsToBounds = true
view.layer.cornerRadius = view.frame.size.width / 2
profileImage.layer.cornerRadius = profileImage.frame.size.width / 2
descriptionLbl.alpha = 0.7
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func profileBtnPressed(_ sender: Any) {
let passValue = UserProfileVC()
let profileTvC = ProfilesTableVC()
print (profileImageBtn.titleLabel!.text!)
var id = (profileImageBtn.titleLabel!.text!)
profileTvC.didSelectProfileBtn(senderID: id)
}
This is the tableViewController, where I everything gets loaded (not where I want to pass the value). I tried passing the value here and then do a prepareForSegue to pass the value to the new UIViewController but the value becomes nil after the segue happens. I am just including code where the .xib call the function from the table view.
class ProfilesTableVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate,UINavigationControllerDelegate, UIImagePickerControllerDelegate{
let cell = CustomCellTableViewCell()
func didSelectProfileBtn(senderID: String) {
senderIDArray.append(senderID)
var index = senderIDArray.count - 1
selectedCellUserID = senderIDArray[index]
performSegue(withIdentifier: "showSendersProfile", sender: Any?.self)
}
This is the UIViewController where I want to pass the variable and display further information from Firebase using that ID
import UIKit
import Firebase
class UserProfileVC: UIViewController {
let customCell = CustomCellTableViewCell()
let profileTvC = ProfilesTableVC()
#IBOutlet weak var profileImage: UIImageView!
#IBOutlet weak var nameLbl: UILabel!
var delegate : Any?
var getName = String()
var getsenderID = String()
let userDataRef = Database.database().reference().child("Users")
override func viewDidLoad() {
super.viewDidLoad()
print("ID is: \(profileTvC.selectedCellUserID)")
let sender = getsenderID
print(sender)
}
}
If you don't want to use protocols, you can addTarget to the button in the tableView - cellForRowAt method, also in that method you set the tag to the row index value.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let profileCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! MoviewReviewCell
reviewCell.profileImageBtn.tag = indexPath.row
reviewCell.profileImageBtn.addTarget(self, action: #selector(tappedOnXibCellButton), for: .touchUpInside)
return reviewCell
}
#objc func tappedOnXibCellButton(sender: UIButton) {
print(sender.tag)
performSegue(withIdentifier: reviewListToDetails, sender: sender.tag)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let identifier = segue.identifier
if identifier == "segueName" {
let destViewController = segue.destination as! DestinationClassViewController
let selectedIndex = sender as! Int
let profileId = profilesList[selectedIndex].id
destViewController.profileId = profileId
}
}
You seem to create a NEW ProfilesTableVC, and try to perform the segue on. The newly created one is not on your view stack, and not from your storyboard.
You could add this while returned cellForRowAt (at the ProfilesTableVC of course):
cell.vcInstance = self
Then in the button click
#IBAction func profileBtnPressed(_ sender: Any) {
print (profileImageBtn.titleLabel!.text!)
var id = (profileImageBtn.titleLabel!.text!)
vcInstance?.didSelectProfileBtn(senderID: id)
}
You can do it with protocols/delegates. I think you tried but there is something wrong with your trial.
Define a callback delegate:
protocol CustomCellDelegate: AnyObject {
func customCell(didSelectButton name: String)
}
You will notice extending AnyObject. This is to allow weak references, try to read about Swift ARC
Then, in your cell:
weak var delegate: CustomCellDelegate?
Then in the profileBtnPressed(_ sender: Any)
#IBAction func profileBtnPressed(_ sender: Any) {
var id = (profileImageBtn.titleLabel!.text!)
delegate?.customCell(didSelectButton: id)
}
When dequeing the cell:
(cell as? CustomCellTableViewCell)?.delegate = self

Tab Bar Item hidden behind tableview / not being shown?

I have an empty view with a tab bar pictured below, when i load a routine a table appears containing the contents, however it seems to overlay the tab bar killing off app navigation. Its not sized in the storyboard to overlay it and its constraint locked to not do so, so im unsure why this is happening, pics of the issue and VC's code below:
VC Code:
import Foundation
import UIKit
import CoreData
class RoutineController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// MARK: - DECLARATIONS
#IBAction func unwindToRoutine(segue: UIStoryboardSegue) {}
#IBOutlet weak var daysRoutineTable: UITableView!
#IBOutlet weak var columnHeaderBanner: UIView!
#IBOutlet weak var todaysRoutineNavBar: UINavigationBar!
#IBOutlet weak var addTOdaysRoutineLabel: UILabel!
let date = Date()
let dateFormatter = DateFormatter()
let segueEditUserExerciseViewController = "editExerciseInRoutineSegue"
//This is the selected routine passed from the previous VC
var selectedroutine : UserRoutine?
// MARK: - VIEWDIDLOAD
override func viewDidLoad() {
super.viewDidLoad()
setupView()
daysRoutineTable.delegate = self
daysRoutineTable.dataSource = self
view.backgroundColor = (UIColor.customBackgroundGraphite())
dateFormatter.dateStyle = .short
dateFormatter.dateFormat = "dd/MM/yyyy"
let dateStr = dateFormatter.string(from: date)
todaysRoutineNavBar.topItem?.title = dateStr + " Routine"
}
// MARK: - VIEWDIDAPPEAR
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.daysRoutineTable.reloadData()
self.updateView()
}
// MARK: - TABLE UPDATE COMPONENTS
private func setupView() {
updateView()
}
// MARK: - TABLE SETUP
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let count = self.selectedroutine?.userexercises?.count
{
print("exercises: \(count)")
return count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? TodaysRoutineTableViewCell else {
fatalError("Unexpected Index Path")
}
cell.backgroundColor = UIColor.customBackgroundGraphite()
cell.textLabel?.textColor = UIColor.white
configure(cell, at: indexPath)
return cell
}
// MARK: - VIEW CONTROLER ELEMENTS VISIBILITY CONTROL
fileprivate func updateView() {
var hasUserExercises = false
if let UserExercise = self.selectedroutine?.userexercises {
hasUserExercises = UserExercise.count > 0
}
addTOdaysRoutineLabel.isHidden = hasUserExercises
columnHeaderBanner.isHidden = !hasUserExercises
daysRoutineTable.isHidden = !hasUserExercises
}
// MARK: - SETTING DATA FOR A TABLE CELL
func configure(_ cell: TodaysRoutineTableViewCell, at indexPath: IndexPath) {
if let userExercise = selectedroutine?.userexercises?.allObjects[indexPath.row]
{
print("\((userExercise as! UserExercise).name)")
cell.todaysExerciseNameLabel.text = (userExercise as! UserExercise).name
cell.todaysExerciseRepsLabel.text = String((userExercise as! UserExercise).reps)
cell.todaysExerciseSetsLabel.text = String((userExercise as! UserExercise).sets)
cell.todaysExerciseWeightLabel.text = String((userExercise as! UserExercise).weight)
}
}
}
requested table constraints
Debug hierarchy
The Segue that sends the user back to the view that looses its tab bar
if segue.identifier == "addToTodaySegue" {
let indexPath = workoutTemplateTable.indexPathForSelectedRow
let selectedRow = indexPath?.row
print("selected row\(selectedRow)")
if let selectedRoutine = self.fetchedResultsController.fetchedObjects?[selectedRow!]
{
if let todaysRoutineController = segue.destination as? RoutineController {
todaysRoutineController.selectedroutine = selectedRoutine
}
}
}
I also feel perhaps the viewDidAppear code may cause the issue, perhaps the super class?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.daysRoutineTable.reloadData()
self.updateView()
Updated storyboard image
I suspect you need to embed your viewController in a UINavigationController.
Consider the following setup:
I suspect your setup is like the upper one:
TapBar -> ViewController -show segue-> ViewController
Which results in a hidden tapbar, like in your description:
While the bottom setup:
TapBar -> NavigationCntroller -rootView-> ViewController -show segue-> ViewController
results in:
which is what you want, how I understood.
Update
It's hard to see. The screenshot of your Storyboard is in pretty low resulution, but the segues look wrong. Double check them. A Segue of type show (e.g push) looks like this:
Also clear project and derived data. Segue type changes sometime are ignored until doing so.
Try calling this self.view.bringSubviewToFront(YourTabControl).
The previous suggestion should work. But the content at the bottom part of tableview will not be visible as the tabbar comes over it. So set the bottom constraint of tableview as the height of tabbar.

Need to update tableView

I'm studying programming in Swift, and I've got this example from a book with a mistake (commented). How can I fix this and update tableView while pressing the Add button? I've read many solutions, but none seem to work. Also, tableView updated when I reloaded simulator. I've been stuck with this for two days, and it's driving me mad! :)
import UIKit
import CoreData
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var managedObjectContext: NSManagedObjectContext!
override func viewDidLoad() {
super.viewDidLoad()
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
managedObjectContext = appDelegate.managedObjectContext! as NSManagedObjectContext
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadBooks() -> Array<AnyObject> {
var error: NSError? = nil
var fetchRequest = NSFetchRequest(entityName: "Book")
let result: [AnyObject] = managedObjectContext!.executeFetchRequest(fetchRequest, error:&error)!
return result
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return loadBooks().count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell
var book: Book = loadBooks()[indexPath.row] as! Book
cell.textLabel!.text = book.title
return cell
}
#IBAction func addNew(sender: AnyObject) {
let entity = NSEntityDescription.entityForName("Book", inManagedObjectContext:managedObjectContext)
var book = Book(entity: entity!,insertIntoManagedObjectContext:managedObjectContext)
book.title = "My Book:" + String(loadBooks().count)
var error: NSError?
managedObjectContext.save(&error)
myTableView.reloadData() //mistake!
}
}
You have to declare your an outlet for your tableview which is probably set up in the according storyboards view controller.
import UIKit
import CoreData
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var managedObjectContext: NSManagedObjectContext!
#IBOutlet weak var myTableView: UITableView!
// your code
}
Please don't forget to connect your table view instance from the storyboard with your new created outlet, by opening code and storyboard side-by-side and draw a line from the dot next to the outlet to the tableview.
Or you can use the way apple describes here (https://developer.apple.com/library/ios/recipes/xcode_help-IB_connections/chapters/CreatingOutlet.html) to create your outlet from the table view on the storyboard.
edit:
Nevermind, i realized that if you wouldnt have had connected the dataSource and delegate, the crash would have happend way before the addNew().
Kie's answer is correct, however to see an actual result you also need to connect the dataSource and delegate of the tableView to your class.
You can do this either in storyboard, or in code in the viewDidLoad method.
override func viewDidLoad(){
super.viewDidLoad()
myTableView.dataSource = self
myTableView.delegate = self
// Additional code
}