I have a main VC, which displays data added by a user, and a VC where the user inputs the data.
What I am trying to do is pass the image from the adding VC to the main VC.
Currently, I get the SIGABRT error when I press save, and the following error message:
2016-04-14 08:07:23.207 On The Go[27697:2680635] -[On_The_Go.Agenda setImage:]: unrecognized selector sent to instance 0x7faf03063900 2016-04-14 08:07:23.212 On The Go[27697:2680635] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[On_The_Go.Agenda setImage:]: unrecognized selector sent to instance 0x7faf03063900' * First throw call stack: ( 0 CoreFoundation 0x000000010442bd85 exceptionPreprocess + 165 1 libobjc.A.dylib 0x0000000106897deb objc_exception_throw + 48 2 CoreFoundation 0x0000000104434d3d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205 3 CoreFoundation 0x000000010437acfa ___forwarding_ + 970 4 CoreFoundation 0x000000010437a8a8 _CF_forwarding_prep_0 + 120 5 On The Go 0x0000000103e97e11 _TFC9On_The_Go22AddTableViewController4savefCSo15UIBarButtonItemT_ + 4897 6 On The Go 0x0000000103e9842a _TToFC9On_The_Go22AddTableViewController4savefCSo15UIBarButtonItemT_ + 58 7 UIKit 0x000000010531da8d -[UIApplication sendAction:to:from:forEvent:] + 92 8 UIKit 0x000000010572b067 -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 152 9 UIKit 0x000000010531da8d -[UIApplication sendAction:to:from:forEvent:] + 92 10 UIKit 0x0000000105490e67 -[UIControl sendAction:to:forEvent:] + 67 11 UIKit 0x0000000105491143 -[UIControl _sendActionsForEvents:withEvent:] + 327 12 UIKit 0x00000001054912be -[UIControl _sendActionsForEvents:withEvent:] + 706 13 UIKit 0x0000000105490263 -[UIControl touchesEnded:withEvent:] + 601 14 UIKit 0x000000010539099f -[UIWindow _sendTouchesForEvent:] + 835 15 UIKit 0x00000001053916d4 -[UIWindow sendEvent:] + 865 16 UIKit 0x000000010533cdc6 -[UIApplication sendEvent:] + 263 17 UIKit 0x0000000105316553 _UIApplicationHandleEventQueue + 6660 18 CoreFoundation 0x0000000104351301 CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 17 19 CoreFoundation 0x000000010434722c __CFRunLoopDoSources0 + 556 20 CoreFoundation 0x00000001043466e3 __CFRunLoopRun + 867 21 CoreFoundation 0x00000001043460f8 CFRunLoopRunSpecific + 488 22 GraphicsServices 0x0000000109efbad2 GSEventRunModal + 161 23 UIKit 0x000000010531bf09 UIApplicationMain + 171 24 On The Go 0x0000000103e9b672 main + 114 25 libdyld.dylib 0x000000010736492d start + 1 26 ??? 0x0000000000000001 0x0 + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)
My code is:
Main VC:
import UIKit
import CoreData
class MainTableViewController: UITableViewController, NSFetchedResultsControllerDelegate, UISearchResultsUpdating {
var content:[Agenda] = []
var fetchResultController:NSFetchedResultsController!
var searchController:UISearchController!
var searchResults:[Agenda] = []
override func viewDidLoad() {
super.viewDidLoad()
let fetchRequest = NSFetchRequest(entityName: "Agenda")
let sortDescriptor = NSSortDescriptor(key: "subject", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
if let managedObjectContext = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext {
fetchResultController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
fetchResultController.delegate = self
do {
try fetchResultController.performFetch()
content = fetchResultController.fetchedObjects as! [Agenda]
} catch {
print(error)
}
}
tableView.estimatedRowHeight = 76.0
tableView.rowHeight = UITableViewAutomaticDimension
searchController = UISearchController(searchResultsController: nil)
tableView.tableHeaderView = searchController.searchBar
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search items..."
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.active {
return searchResults.count
} else {
return content.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! MainTableViewCell
// Configure the cell...
let agenda = (searchController.active) ? searchResults[indexPath.row] : content[indexPath.row]
cell.subjectLabel.text = agenda.subject
cell.deadlineLabel.text = agenda.deadline
cell.iconImageView.image = UIImage(data: agenda.image!)
if agenda.urgent == true {
cell.urgentImageView.image = UIImage(named: "urgent")
cell.urgentImageView.image = cell.urgentImageView.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
cell.urgentImageView.tintColor = UIColor(red: 212.0/255.0, green: 106.0/255.0, blue: 106.0/255.0, alpha: 1.0)
} else {
cell.urgentImageView.image = nil
}
cell.subjectLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
cell.subjectLabel.numberOfLines = 999
cell.deadlineLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
cell.deadlineLabel.numberOfLines = 999
cell.subjectLabel.sizeToFit()
cell.deadlineLabel.sizeToFit()
cell.subjectLabel.translatesAutoresizingMaskIntoConstraints = false
return cell
}
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Share", handler: { (action, indexPath) -> Void in
let defaultText = "I've got to " + self.content[indexPath.row].subject
let activityController = UIActivityViewController(activityItems: [defaultText], applicationActivities: nil)
self.presentViewController(activityController, animated: true, completion: nil)
})
let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler: { (action, indexPath) -> Void in
if let managedObjectContext = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext {
let itemToDelete = self.fetchResultController.objectAtIndexPath(indexPath) as! Agenda
managedObjectContext.deleteObject(itemToDelete)
do {
try managedObjectContext.save()
} catch {
print(error)
}
}
})
shareAction.backgroundColor = UIColor(red: 28.0/255.0, green: 165.0/255.0, blue: 253.0/255.0, alpha: 1.0)
deleteAction.backgroundColor = UIColor(red: 202.0/255.0, green: 202.0/255.0, blue: 203.0/255.0, alpha: 1.0)
return [deleteAction, shareAction]
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if searchController.active {
return false
} else {
return true
}
}
func controllerWillChangeContent(controller: NSFetchedResultsController) {
tableView.beginUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
if let _newIndexPath = newIndexPath {
tableView.insertRowsAtIndexPaths([_newIndexPath], withRowAnimation: .Fade)
}
case .Delete:
if let _indexPath = indexPath {
tableView.deleteRowsAtIndexPaths([_indexPath], withRowAnimation: .Fade)
}
case .Update:
if let _indexPath = indexPath {
tableView.reloadRowsAtIndexPaths([_indexPath], withRowAnimation: .Fade)
}
default:
tableView.reloadData()
}
content = controller.fetchedObjects as! [Agenda]
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
tableView.endUpdates()
}
func filterContentForSearchText(searchText: String) {
searchResults = content.filter({ (content:Agenda) -> Bool in
let nameMatch = content.subject.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
let deadlineMatch = content.deadline.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
return nameMatch != nil || deadlineMatch != nil
})
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
if let searchText = searchController.searchBar.text {
filterContentForSearchText(searchText)
tableView.reloadData()
}
}
@IBAction func unwindToHomeScreen(segue: UIStoryboardSegue) {
}
}
Adding VC:
import UIKit
import CoreData
class AddTableViewController: UITableViewController {
// MARK: - Table view data source
@IBOutlet var photoImageView:UIImageView!
@IBOutlet var subjectTextField:UITextField!
@IBOutlet var deadlineTextField:UITextField!
@IBOutlet var yesButton:UIButton!
@IBOutlet var noButton:UIButton!
var urgent = true
var content:Agenda!
var imageName:String = ""
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView(frame: CGRectZero)
title = "Add an item"
photoImageView.image = UIImage(named: imageName)
photoImageView.image = photoImageView.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
photoImageView.tintColor = UIColor.whiteColor()
if imageName == "cup" {
photoImageView.backgroundColor = UIColor(red: 137.0/255.0, green: 72.0/255.0, blue: 0.0/255.0, alpha: 1.0)
} else if imageName == "transport" {
photoImageView.backgroundColor = UIColor.blueColor()
} else if imageName == "beach" {
photoImageView.backgroundColor = UIColor.yellowColor()
} else if imageName == "weather" {
photoImageView.backgroundColor = UIColor(red: 255.0/255.0, green: 122.0/255.0, blue: 255.0/255.0, alpha: 1.0)
} else if imageName == "gear" {
photoImageView.backgroundColor = UIColor(red: 106.0/255.0, green: 207.0/255.0, blue: 255.0/255.0, alpha: 1.0)
} else if imageName == "money" {
photoImageView.backgroundColor = UIColor(red: 110.0/255.0, green: 110.0/255.0, blue: 110.0/255.0, alpha: 1.0)
} else if imageName == "technology-1" {
photoImageView.backgroundColor = UIColor.orangeColor()
} else if imageName == "web" {
photoImageView.backgroundColor = UIColor(red: 255.0/255.0, green: 114.0/255.0, blue: 110.0/255.0, alpha: 1.0)
} else if imageName == "people" {
photoImageView.backgroundColor = UIColor(red: 104.0/255.0, green: 251.0/255.0, blue: 208.0/255.0, alpha: 1.0)
} else if imageName == "nature" {
photoImageView.backgroundColor = UIColor(red: 110.0/255.0, green: 118.0/255.0, blue: 255.0/255.0, alpha: 1.0)
} else if imageName == "draw" {
photoImageView.backgroundColor = UIColor.purpleColor()
} else if imageName == "technology" {
photoImageView.backgroundColor = UIColor(red: 131.0/255.0, green: 249.0/255.0, blue: 2.0/255.0, alpha: 1.0)
} else if imageName == "screen" {
photoImageView.backgroundColor = UIColor(red: 135.0/255.0, green: 134.0/255.0, blue: 135.0/255.0, alpha: 1.0)
} else if imageName == "shop" {
photoImageView.backgroundColor = UIColor(red: 210.0/255.0, green: 120.0/255.0, blue: 255.0/255.0, alpha: 1.0)
} else if imageName == "arrow" {
photoImageView.backgroundColor = UIColor.blackColor()
}
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func save(sender:UIBarButtonItem) {
let subject = subjectTextField.text
let deadline = deadlineTextField.text
let icon = UIImage(named: imageName)
if subject == "" || deadline == "" || icon == "" {
let alertController = UIAlertController(title: "Oops!", message: "Not all of the fields have been filled in. Please fill them in before proceeding.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
return
}
if let managedObjectContext = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext {
content = NSEntityDescription.insertNewObjectForEntityForName("Agenda", inManagedObjectContext: managedObjectContext) as! Agenda
content.subject = subject!
content.deadline = deadline!
content.urgent = urgent
if let iconImage = photoImageView.image {
content.image = UIImagePNGRepresentation(iconImage)
}
do {
try managedObjectContext.save()
} catch {
print(error)
return
}
}
dismissViewControllerAnimated(true, completion: nil)
}
@IBAction func toggleUrgentButton(sender: UIButton) {
if sender == yesButton {
urgent = true
yesButton.backgroundColor = UIColor(red: 170.0/255.0, green: 240.0/255.0, blue: 255.0/255.0, alpha: 1.0)
noButton.backgroundColor = UIColor.lightGrayColor()
} else if sender == noButton {
urgent = false
yesButton.backgroundColor = UIColor.lightGrayColor()
noButton.backgroundColor = UIColor(red: 170.0/255.0, green: 240.0/255.0, blue: 255.0/255.0, alpha: 1.0)
}
}
@IBAction func unwindToIcon(segue: UIStoryboardSegue) {
}
}
My class (Agenda):
import Foundation
import CoreData
class Agenda:NSManagedObject {
@NSManaged var subject:String
@NSManaged var deadline:String
@NSManaged var urgent:NSNumber?
@NSManaged var image:NSData?
}
The image gets chosen from another VC, but if you need that code, feel free to ask.
I want to get the image into the main VC's iconImageView.