My textView text is not saving itself when i leave the cell - ios

I am trying to do something similar to Notes app and I am stuck with what i think is such a stupid thing. When i enter my app there is a add button to add new notes. I can then rename it and enter to a new view controller which consist of only title and textView on the whole screen. I use Codable and UserDefaults to save the data. Title is saving just fine, but whatever i type in textView and then come back to see all rows in tableView and i come back to that particular "note" all my typed text is gone.
This is my didSelectRowAt method
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let vc = storyboard?.instantiateViewController(withIdentifier: "Note") as? NoteViewController {
navigationController?.pushViewController(vc, animated: true)
vc.bodyText = note[indexPath.row].body
vc.titleText = note[indexPath.row].title
if note[indexPath.row].title == "New note" {
let ac = UIAlertController(title: "Rename note", message: "Please enter name for a new note", preferredStyle: .alert)
ac.addTextField()
ac.addAction(UIAlertAction(title: "Cancel", style: .default))
ac.addAction(UIAlertAction(title: "Rename", style: .default) { [unowned self, ac] _ in
let newName = ac.textFields![0]
note[indexPath.row].title = newName.text!
self.tableView.reloadData()
vc.viewDidLoad()
self.save()
})
present(ac, animated: true)
} else {
}
}
}
And my NoteViewController
class NoteViewController: UIViewController, UITextViewDelegate {
#IBOutlet var textView: UITextView!
var bodyText: String?
var titleText: String?
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(image: .checkmark, style: .plain, target: self, action: #selector(saveNote))
title = titleText
textView.text = bodyText
}
And Save()
func save() {
let jsonEncoder = JSONEncoder()
if let savedData = try? jsonEncoder.encode(note) {
let defaults = UserDefaults.standard
defaults.set(savedData, forKey: "note")
} else {
print("failed to load data")
}
}
I tried changing my method didSelectRowAt by adding my save() to different places but it's only saving title.

You may use a onSavingTap closure in the NoteViewController to pass the data back to the main view controller.
class NoteViewController: UIViewController, UITextViewDelegate {
var onSavingTap: ((String) -> Void)?
#IBOutlet var textView: UITextView!
var bodyText: String?
var titleText: String?
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(image: .checkmark, style: .plain, target: self, action: #selector(saveNote))
title = titleText
textView.text = bodyText
}
#objc func saveNote() {
onSavingTap?(textView.text ?? "")
}
}
then in the didSelectRow method you set the closure to update your data array as follows:
vc.onSavingTap = { [weak self] body in
self?.note[indexPath.row].body = body
self?.save()
}

Related

How to filter array from selected tableviewcell in swift?

I am quite puzzled on how will I construct my codes regarding on how I will filter the selected array from a tableviewcell. The JSON below is the content of the tableview which displays like
[
{
"hospitalNumber": "00000001",
"patientName": "Test Patient",
"totalAmount": 1111.3
},
{
"hospitalNumber": "00000002",
"patientName": "Test Patient 2",
"totalAmount": 1312
},
{
"hospitalNumber": "00000003",
"patientName": "Test Patient 3",
"totalAmount": 475
}
]
The problem is how can I display the selected hospitalNumber and patientName in the next View Controller, which will display like
This is what my `PaymentDetailsViewController' have:
var patientList: [Patient]! {
didSet {
latestCreditedAmountTableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
getPatientList()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showPatientPaymentDetailsVC" {
if let patientPaymentDetailsVC = segue.destination as? PatientPaymentDetailsViewController {
patientPaymentDetailsVC.isBrowseAll = self.isBrowseAll
if !isBrowseAll {
patientPaymentDetailsVC.patientPayoutDetails = self.selectedPatientPayment
patientPaymentDetailsVC.currentRemittance = self.currentRemittance
patientPaymentDetailsVC.doctorNumber = self.doctorNumber
}
}
}
}
func getPatientList() {
SVProgressHUD.setDefaultMaskType(.black)
SVProgressHUD.show(withStatus: "Retrieving Patient List")
APIService.PatientList.getPatientList(doctorNumber: doctorNumber, periodId: currentRemittance.periodId) { (patientListArray, error) in
guard let patientListPerPayout = patientListArray, error == nil else {
if let networkError = error {
switch networkError {
case .noRecordFound:
let alertController = UIAlertController(title: "No Record Found", message: "You don't have current payment remittance", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
case .noNetwork:
let alertController = UIAlertController(title: "No Network", message: "\(networkError.rawValue)", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
default:
let alertController = UIAlertController(title: "Error", message: "There is something went wrong. Please try again", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
}
}
SVProgressHUD.dismiss()
return
}
self.patientList = patientListPerPayout
self.latestCreditedAmountTableView.reloadData()
SVProgressHUD.dismiss()
return
}
}
**getPerPatientPAyoutDetails(from: String) function**
func getPerPatientPayoutDetails(from: String) {
SVProgressHUD.setDefaultMaskType(.black)
SVProgressHUD.showInfo(withStatus: "Retrieving Patient Details")
APIService.PatientList.getPatientDetailsPerPayout(periodId: currentRemittance.periodId, doctorNumber: doctorNumber, parameterName: .selectedByHospitalNumber, hospitalNumber: from) { (patientPayout, error) in
guard let patientPerPayoutDetails = patientPayout, error == nil else {
if let networkError = error {
switch networkError {
case .noRecordFound:
let alertController = UIAlertController(title: "No Record Found", message: "You don't have current payment remittance", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
case .noNetwork:
let alertController = UIAlertController(title: "No Network", message: "\(networkError.rawValue)", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
default:
let alertController = UIAlertController(title: "Error", message: "There is something went wrong. Please try again", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
}
}
SVProgressHUD.dismiss()
return
}
self.selectedPatientPayment = patientPerPayoutDetails
print(self.selectedPatientPayment)
SVProgressHUD.dismiss()
return
}
}
Base on the gePatientList() function, it will just pull the full list of the patients. I don't know how I will pass the data of the selected patient to another VC. Hope you can help me. Thank you so much.
Codes that might help to understand the flow of my codes
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.section {
case 0: break
case 1: let selectedpatient = patientList[indexPath.row].hospitalNumber
print(selectedpatient!)
self.isBrowseAll = false
getPerPatientPayoutDetails(from: selectedpatient!)
default: break
}
}
Below is the another View Controller that will display the patientName and hospitalNumber
PatientPaymentDetailsVC
class PatientPaymentDetailsViewController: UIViewController {
#IBOutlet weak var patientProcedureTableView: UITableView!
#IBOutlet weak var hospitalNumberLabel: UILabel!
#IBOutlet weak var patientNameLabel: UILabel!
var currentRemittance: CurrentRemittance!
var doctorNumber: String!
var isBrowseAll: Bool!
var patientList: [Patient]!
var patientPayoutDetails: [PatientPayoutDetails]!
override func viewDidLoad() {
super.viewDidLoad()
setupPatientInfo()
}
//MARK: FUNCTION
func setupPatientInfo() {
self.patientNameLabel.text = patient.patientName
self.hospitalNumberLabel.text = patient.hospitalNumber
}
The pulled data under the getPerPatientPayoutDetails function from the didselect will be displayed in PatientPaymentDetailsVC. Below is the output, as you can I see I can pull the data under getPerPatientPayoutDetails but the patientName and hospitalNumber does not display the data.
First of all don't get the data from the table view cell, get it from the data source
Connect the segue to the cell.
Delete the entire method didSelectRowAt
When prepare(for segue is called the sender parameter is the cell.
Get the index path from the cell and get the patient at that index path.
Rather than passing multiple parameters declare a var patient : Patient! property in the destination controller and hand over the patient instance.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "showPatientPaymentDetailsVC",
let cell = sender as? UITableViewCell,
let indexPath = tableView.indexPath(for: cell) else { return }
let patient = patientList[indexPath.row]
getPerPatientPayoutDetails(from: patient.hospitalNumber)
let patientPaymentDetailsVC = segue.destination as! PatientPaymentDetailsViewController
patientPaymentDetailsVC.patient = patient
patientPaymentDetailsVC.patientPayoutDetails = self.selectedPatientPayment
patientPaymentDetailsVC.currentRemittance = self.currentRemittance
patientPaymentDetailsVC.doctorNumber = self.doctorNumber
}
class PatientPaymentDetailsViewController: UIViewController {
#IBOutlet weak var patientProcedureTableView: UITableView!
#IBOutlet weak var hospitalNumberLabel: UILabel!
#IBOutlet weak var patientNameLabel: UILabel!
var currentRemittance: CurrentRemittance!
var doctorNumber = ""
var isBrowseAll = false
var patient : Patient!
var patientPayoutDetails: [PatientPayoutDetails]!
override func viewDidLoad() {
super.viewDidLoad()
setupPatientInfo()
}
//MARK: FUNCTION
func setupPatientInfo() {
self.patientNameLabel.text = patient.patientName
self.hospitalNumberLabel.text = patient.hospitalNumber
}
Side note:
Don't declare patientList as implicit unwrapped optional, declare it as non-optional empty array
var patientList : [Patient]()
Use tableView(_:didSelectRowAt:) method by conforming to UITableViewDelegate.
Get the selected patient as displayed below:
selectedPatient = tableView[indexpath.row] as! [String:Any]
As per your edited question, try this:
let patient = patientList[indexPath.row] as! Patient

Parsing JSON Tableview Information as Separate Strings

I am currently trying to use information in Tableview cells that I have populated with JSON to execute various operations but I am unable to call the specific information due to the fact that it isn't in individual strings. Is there any way to take the group of data I have pulled into each tableview cell and turn it into a series of individual strings? Here is what I currently have:
import UIKit
import GoogleMobileAds
class OngoingViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var userUsernameLabel: UILabel!
#IBOutlet weak var bannerView: GADBannerView!
#IBOutlet weak var ongoingTable: UITableView!
var list:[MyStruct] = [MyStruct]()
struct MyStruct
{
var user1 = ""
var user2 = ""
var wager = ""
var amount = ""
init(_ user1:String, _ user2:String, _ wager:String, _ amount:String)
{
self.user1 = user1
self.user2 = user2
self.wager = wager
self.amount = amount
}
}
override func viewDidLoad() {
super.viewDidLoad()
let username = UserDefaults.standard.string(forKey: "userUsername")!
userUsernameLabel.text = username
/// The banner view.
print("Google Mobile Ads SDK version: " + GADRequest.sdkVersion())
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
bannerView.rootViewController = self
bannerView.load(GADRequest())
ongoingTable.dataSource = self
ongoingTable.delegate = self
get_data("http://cgi.soic.indiana.edu/~team10/ongoingWagers.php")
}
func get_data(_ link:String)
{
let url:URL = URL(string: link)!
var request = URLRequest(url:url);
request.httpMethod = "POST";
let postString = "a=\(userUsernameLabel.text!)";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
self.extract_data(data)
}
task.resume()
}
func extract_data(_ data:Data?)
{
let json:Any?
if(data == nil)
{
return
}
do{
json = try JSONSerialization.jsonObject(with: data!, options: [])
}
catch
{
return
}
guard let data_array = json as? NSArray else
{
return
}
for i in 0 ..< data_array.count
{
if let data_object = data_array[i] as? NSDictionary
{
if let data_user1 = data_object["id"] as? String,
let data_user2 = data_object["id2"] as? String,
let data_wager = data_object["wager"] as? String,
let data_amount = data_object["amount"] as? String
{
list.append(MyStruct(data_user1, data_user2, data_wager, data_amount))
}
}
}
refresh_now()
}
func refresh_now()
{
DispatchQueue.main.async(
execute:
{
self.ongoingTable.reloadData()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.ongoingTable.dequeueReusableCell(withIdentifier: "owcell", for: indexPath) as! OngoingTableViewCell
cell.infoLabel.text = list[indexPath.row].user1 + " " + list[indexPath.row].user2 + " " + list[indexPath.row].wager + " " + list[indexPath.row].amount
cell.user1Button.tag = indexPath.row
cell.user1Button.addTarget(self, action: #selector(OngoingViewController.user1Action), for: .touchUpInside)
cell.user2Button.tag = indexPath.row
cell.user2Button.addTarget(self, action: #selector(OngoingViewController.user2Action), for: .touchUpInside)
return cell
}
#IBAction func user1Action(sender: UIButton) {
let user1Alert = UIAlertController(title: "Wait a second!", message: "Are you sure this user has won this wager?", preferredStyle: UIAlertControllerStyle.alert)
user1Alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { action in
let user1ConfirmationAlert = UIAlertController(title: "Great!", message: "Please wait for the other user to confirm the winner of this wager.", preferredStyle: UIAlertControllerStyle.alert)
user1ConfirmationAlert.addAction(UIAlertAction(title: "Got It!", style: UIAlertActionStyle.default, handler: nil))
self.present(user1ConfirmationAlert, animated: true, completion: nil)
}))
user1Alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: nil))
self.present(user1Alert, animated: true, completion: nil)
}
#IBAction func user2Action(sender: UIButton) {
let user2Alert = UIAlertController(title: "Wait a second!", message: "Are you sure this user has won this wager?", preferredStyle: UIAlertControllerStyle.alert)
user2Alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { action in
let user2ConfirmationAlert = UIAlertController(title: "Great!", message: "Please wait for the other user to confirm the winner of this wager.", preferredStyle: UIAlertControllerStyle.alert)
user2ConfirmationAlert.addAction(UIAlertAction(title: "Got It!", style: UIAlertActionStyle.default, handler: nil))
self.present(user2ConfirmationAlert, animated: true, completion: nil)
}))
user2Alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: nil))
self.present(user2Alert, animated: true, completion: nil)
}
}
Here is the OngoingTableViewCell subclass:
import UIKit
class OngoingTableViewCell: UITableViewCell {
#IBOutlet weak var infoLabel: UILabel!
#IBOutlet weak var user1Button: UIButton!
#IBOutlet weak var user2Button: UIButton!
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
}
}
You have an array of MyStruct structures, that contain entries for user1, user1, wager, and amount. That's good.
You're using tags on the buttons as a way of figuring out the selected cell, which is not ideal. Instead I would suggest using the sender parameter to figure out the indexPath of the cell that contains the button. See the bottom of my answer for the details of a better way to do it.
In any case, once you have a row number, you can easily get to the data for that wager by indexing into your array:
#IBAction func user1Action(sender: UIButton) {
selectedRow = sender.tag
//or, using my function:
selectedRow = tableView.indexPathForView(sender)
//Get the wager for the button the user tapped on.
let thisWager = list[selectedRow]
}
If you want to take action on the wager once the user taps a button in your UIAlertController, don't use a nil handler on the your second alert controller. Instead, pass in a closure that uses the selectedRow parameter from the code above to index into the list of wagers, or even use the thisWager local variable I show in my code.
Getting the indexPath of the button the user taps on:
I created a simple extension to UITableView that lets you pass in a UIView (like the sender from a button action) and get back the indexPath that contains that view.
That extension is dirt-simple. Here's how it looks:
public extension UITableView {
/**
This method returns the indexPath of the cell that contains the specified view
- Parameter view: The view to find.
- Returns: The indexPath of the cell containing the view, or nil if it can't be found
*/
func indexPathForView(_ view: UIView) -> IndexPath? {
let origin = view.bounds.origin
let viewOrigin = self.convert(origin, from: view)
let indexPath = self.indexPathForRow(at: viewOrigin)
return indexPath
}
}
And you can call that function from your button's actions:
#IBAction func buttonTapped(_ button: UIButton) {
if let indexPath = self.tableView.indexPathForView(button) {
print("Button tapped at indexPath \(indexPath)")
}
else {
print("Button indexPath not found")
}
}
The whole project can be found on Github at this link: TableViewExtension

Why is my string becoming nil when used as the title of an action sheet?

In an app I am currently writing, I have a string named 'User' which stores the user's name for a game. The value of the string, when printed anywhere else in the Swift file, prints the value that I have set, as an optional.
If I try to use this string as the title of an action sheet action, the string is automatically set to nil, which I can see as both the title of the action and which is printed when I ask it to print(user).
If anyone could shed some light as to why this is happening, or how to prevent it, that would be great. I have also posted my Swift file below, thanks.
import UIKit
class MainViewController: UIViewController {
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var firstView: UIView!
#IBOutlet weak var secondView: UIView!
var user:String!
var playerTwo:String!
var playerThree:String!
var playerFour:String!
var playerFive:String!
var playerSix:String!
var userCards = [String]()
override func viewDidLoad() {
super.viewDidLoad()
firstView?.isHidden = false
secondView?.isHidden = true
}
#IBAction func valueDidChange(_ sender: UISegmentedControl) {
switch segmentedControl.selectedSegmentIndex {
case 0:
firstView.isHidden = false
secondView.isHidden = true
case 1:
firstView.isHidden = true
secondView.isHidden = false
default:
break;
}
}
#IBAction func confirm(_ sender: UIButton) {
let alertController = UIAlertController(title: "Action Sheet", message: "What would you like to do?", preferredStyle: .actionSheet)
let userButton = UIAlertAction(title: user /* Here I have tried with putting both 'user', and "\(user)"*/, style: .default, handler: { (action) -> Void in
print("User button tapped")
})
let deleteButton = UIAlertAction(title: "Delete button test", style: .destructive, handler: { (action) -> Void in
print("Delete button tapped")
})
let cancelButton = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
print("Cancel button tapped")
})
alertController.addAction(userButton)
alertController.addAction(deleteButton)
alertController.addAction(cancelButton)
self.present(alertController, animated: true, completion: nil)
}
}
The value is passed into the above file directly from this code in another file:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showMainController" {
let VC = segue.destination as! MainViewController
VC.user = self.user
if playerTwo != nil {
VC.playerTwo = self.playerTwo
}
if playerThree != nil {
VC.playerThree = self.playerThree
}
if playerFour != nil {
VC.playerFour = self.playerFour
}
if playerFive != nil {
VC.playerFive = self.playerFive
}
if playerSix != nil {
VC.playerSix = self.playerSix
}
}
}
The value is, however, passed through several view controllers, and is initially set here:
if (meTextField.text?.isEmpty)! == false {
let p1 = meTextField.text!
initialPlayersDict["player1"] = "\(p1)"
if errLabelNotBlank {
errorLabel.text = ""
errLabelNotBlank = false
}
}

UIAlertController action sheet whatsapp style

Does anyone knows how to create an UIAlertController like that one that whatsapp did in the next attachment (beside of creating custom UI)
well, as a result from the discussion above, a solution found.
basic idea is to use "contentViewController"
implementation smaple
ViewController.swift
#IBAction func testActionSheetAction(_ sender: Any) {
let sheet = UIAlertController(title: "test", message: nil, preferredStyle: .actionSheet)
let phoneAction = UIAlertAction(title: "", style: .default) { (_) in
print("phone action")
}
phoneAction.mode = .phone
sheet.addAction(phoneAction)
let homeAction = UIAlertAction(title: "", style: .default) { (_) in
print("home action")
}
homeAction.mode = .home
sheet.addAction(homeAction)
sheet.addAction(UIAlertAction(title: "cancel", style: .cancel, handler: nil))
self.present(sheet, animated: true, completion: nil)
}
ActionSheetContentViewController.swift
import UIKit
extension UIAlertAction{
var mode : ActionSheetContentViewController.Mode?{
set{
let vc = ActionSheetContentViewController.viewController(with: newValue)
self.setValue(vc, forKey: "contentViewController")
}
get{
if let vc = value(forKey: "contentViewController") as? ActionSheetContentViewController{
return vc.mode
}
return nil
}
}
}
class ActionSheetContentViewController: UIViewController {
enum Mode{
case home
case phone
var image : UIImage{
get{
switch self {
case .home: return #imageLiteral(resourceName: "icon_home")
case .phone: return #imageLiteral(resourceName: "icon_phone")
}
}
}
var title : String{
get{
switch self {
case .home: return NSLocalizedString("home", comment: "home")
case .phone: return NSLocalizedString("phone", comment: "phone")
}
}
}
}
#IBOutlet weak var label: UILabel!
#IBOutlet weak var imaegView: UIImageView!
var mode : Mode?
override func viewDidLoad() {
super.viewDidLoad()
label.text = mode?.title
imaegView.image = mode?.image
}
class func viewController(with mode : Mode?) -> UIViewController{
let storyboard = UIStoryboard(name: "Main", bundle: .main)
let vc = storyboard.instantiateViewController(withIdentifier: "ActionSheetContentViewController") as! ActionSheetContentViewController
vc.mode = mode
return vc
}
}
ActionSheetContentViewController in storyboard
a screenshot
Yes, you need to add a UITableView to the UIAlertController.
alertController.setValue([customTableGoesHere], forKey: "contentViewController")

Set navbar item button to new title

Good day. I'm facing a weird issue, I'd like to set the right navigation item to Done in my next when I've selected a row. I tried it, and it's worked. But it's breaking however, because the function which implements the doneEditing body, is only in the next view controller, any help will be really appreciated. This is my code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "editContact" {
let indexPath = tableView.indexPathForSelectedRow()
let destinationVC: NewCategoryViewController = segue.destinationViewController as! NewCategoryViewController
let contact:Contact = fetchedResultController.objectAtIndexPath(indexPath!) as! Contact
destinationVC.contact = contact
var rightAddBarButtonItem:UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "doneEditing:")
destinationVC.navigationItem.rightBarButtonItem = rightAddBarButtonItem
}
}
and my next view controller is :
import UIKit
import CoreData
class NewCategoryViewController: UIViewController {
// MARK: - Properties
var contact: Contact? = nil
// initialize the core data context:
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
// MARK: - Outlets
#IBOutlet weak var imageHolder: UIImageView!
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var phoneField: UITextField!
#IBOutlet weak var categoryField: UITextField!
// MARK: - Actions
#IBAction func savebtn(sender: AnyObject) {
let entity = NSEntityDescription.entityForName("Contact", inManagedObjectContext: context!)
let newContact = Contact(entity: entity!, insertIntoManagedObjectContext: context)
newContact.name = nameField.text
newContact.email = emailField.text
newContact.phone = phoneField.text
//newContact.photo = UIImageJPEGRepresentation(imageHolder.image, 1)
var error: NSError?
context?.save(&error)
if let errorSaving = error {
var alert = UIAlertController(title: "Alert", message: "Couldn't save contact !!!", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
} else {
nameField.text = ""
emailField.text = ""
phoneField.text = ""
var alert = UIAlertController(title: "Notification", message: "Contact added", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = contact?.name
if contact != nil {
nameField.text = contact?.name
emailField.text = contact?.email
phoneField.text = contact?.phone
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func doneEditing() {
}
}
change target from self to destinationVC.
Use this:
var rightAddBarButtonItem:UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: destinationVC, action: "doneEditing:")
self should be used when the selector is defined in the same class which makes the call. In this case the selector is in a separate class.
OR
I would suggest you to add the right bar button in the viewDidLoad method of NewCategoryViewController. In which case the code will be:
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "doneEditing:")
AND
implement doneEditing: method as
func doneEditing(sender: UIBarButtonItem) {
}

Resources