For swift learning purposes, I'm work on personal Core Data project. So far everything is working, but I cannot figure out how to optimize the code. By optimization I mean only visual optimization, the performance is different story and is too early for me. In the class below I'm using dateFormatter quite often, so I'm trying to avoid it. Seems that I miss something fundamental in the programming, which is not surprise for absolute beginner and amateur.
import UIKit
import CoreData
class AddEditViewController: UIViewController {
@IBOutlet weak var startDateTextField: UITextField!
@IBOutlet weak var endDateTextField: UITextField!
@IBOutlet weak var shipNameTextField: UITextField!
@IBOutlet weak var positionOnBoardTextField: UITextField!
@IBOutlet weak var workingDaysLabel: UILabel!
var startDatePassedFromTable: NSDate!
var endDatePassedFromTable: NSDate!
var shipNamePassedFromTable: String!
var positionOnBoardPassedFromTable: String!
var workingDaysPassedFromTable: Int!
var exsistingContract: NSManagedObject!
override func viewDidLoad() {
super.viewDidLoad()
// Load the view with the data passed from the table
if (exsistingContract != nil) {
self.title = "Edit Contract"
var dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT+0:00")
dateFormatter.dateFormat = "dd-MM-yyyy"
startDateTextField.text = dateFormatter.stringFromDate(startDatePassedFromTable)
endDateTextField.text = dateFormatter.stringFromDate(endDatePassedFromTable)
shipNameTextField.text = shipNamePassedFromTable
positionOnBoardTextField.text = positionOnBoardPassedFromTable
workingDaysLabel.text = "\(workingDaysPassedFromTable)"
} else {
self.title = "Add Contract"
}
}
// Start Date Text Field- action and format for DatePicker
@IBAction func startDateTextFieldEditing(sender: UITextField) {
var datePickerView:UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: Selector("startDatePickerValueChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
func startDatePickerValueChanged(sender: UIDatePicker) {
var dateformatter = NSDateFormatter()
dateformatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateformatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateformatter.dateFormat = "dd-MM-yyyy"
startDateTextField.text = dateformatter.stringFromDate(sender.date)
return calculateWorkingDays()
}
// End Date Text Field - action and format for DatePicker
@IBAction func endDateTextFieldEditing(sender: UITextField) {
var datePickerView:UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: Selector("endDatePickerValueChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
func endDatePickerValueChanged(sender: UIDatePicker) {
var dateformatter = NSDateFormatter()
dateformatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateformatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateformatter.dateFormat = "dd-MM-yyyy"
endDateTextField.text = dateformatter.stringFromDate(sender.date)
return calculateWorkingDays()
}
// Hide keyboard or DatePicker
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
// Calculate the working days from String -> NSDate of startDateTextField and endDateTextField
func calculateWorkingDays() {
// Check if the startDateTextField AND endDateTextField are not empty
if !startDateTextField.text.isEmpty && !endDateTextField.text.isEmpty {
// Date format and localisation
let calendar = NSCalendar.currentCalendar()
let unit: NSCalendarUnit = .CalendarUnitDay
var dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT+0:00")
dateFormatter.dateFormat = "dd-MM-yyyy"
let startDatePicker: NSDate = dateFormatter.dateFromString(startDateTextField.text)!
let endDatePicker: NSDate = dateFormatter.dateFromString(endDateTextField.text)!
// Calculate the diference and set the workingDays Label to Days -> String from Int + 1
let components = calendar.components(unit, fromDate: startDatePicker, toDate: endDatePicker, options: nil)
workingDaysLabel.text = "\(components.day + 1)"
}
}
@IBAction func buttonSavePressed(sender: UIBarButtonItem) {
// Check for empty TextField
if startDateTextField.text.isEmpty || endDateTextField.text.isEmpty || shipNameTextField.text.isEmpty || positionOnBoardTextField.text.isEmpty {
// Allert message with OK button
let alertController = UIAlertController(title: "Error Save Contract", message: "Start and End Date are required", preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Cancel, handler: nil)
alertController.addAction(okAction)
presentViewController(alertController, animated: true, completion: nil)
} else {
// Save data and return to the root controller
// Check if contract is exsisting and EDIT or NEW for save new contract
var appDelegate: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context: NSManagedObjectContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName("Contract", inManagedObjectContext: context)!
var dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT+0:00")
dateFormatter.dateFormat = "dd-MM-yyyy"
// Check if contract exsist
if (exsistingContract != nil) {
// Edit exsisting contract
exsistingContract.setValue((dateFormatter.dateFromString(startDateTextField.text)), forKey: "startdate")
exsistingContract.setValue((dateFormatter.dateFromString(endDateTextField.text)), forKey: "enddate")
exsistingContract.setValue(shipNameTextField.text, forKey: "ship")
exsistingContract.setValue(positionOnBoardTextField.text, forKey: "position")
exsistingContract.setValue(workingDaysLabel.text?.toInt(), forKey: "workingdays")
} else {
// Create new contract
var newContractData = Contract(entity: entity, insertIntoManagedObjectContext: context)
newContractData.startdate = dateFormatter.dateFromString(startDateTextField.text)!
newContractData.enddate = dateFormatter.dateFromString(endDateTextField.text)!
newContractData.ship = shipNameTextField.text
newContractData.position = positionOnBoardTextField.text
newContractData.workingdays = workingDaysLabel.text!.toInt()!
}
// Save and return to root
context.save(nil)
self.navigationController?.popToRootViewControllerAnimated(true)
}
}
@IBAction func cancelButtonPressed(sender: UIBarButtonItem) {
self.navigationController?.popToRootViewControllerAnimated(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You can create only one instance on NSDateFormatter and use it where you need it: