Trying to add to the tutorial and save from a textfield and label to core data.
- Attributes are
dollarAmount
halvesAmount
quarterAmount
dimeAmount
nickelAmount
pennyAmount
import Foundation
import CoreData
import CoreLocation
extension Location {
@nonobjc public class func fetchRequest() → NSFetchRequest {
return NSFetchRequest(entityName: “Location”)
}
@NSManaged public var latitude: Double
@NSManaged public var longitude: Double
@NSManaged public var date: Date
@NSManaged public var locationDescription: String
@NSManaged public var category: String
@NSManaged public var placemark: CLPlacemark?
@NSManaged public var photoID: NSNumber?
@NSManaged public var dollarAmount: Double
@NSManaged public var halvesAmount: Double
@NSManaged public var quarterAmount: Double
@NSManaged public var dimeAmount: Double
@NSManaged public var nickelAmount: Double
@NSManaged public var pennyAmount: Double
@NSManaged public var dollarCount: Double
}
extension Location : Identifiable {
}
and
import UIKit
import CoreLocation
import CoreData
private let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
return formatter
}()
class LocationDetailsViewController: UITableViewController {
@IBOutlet var descriptionTextView: UITextView!
@IBOutlet var categoryLabel: UILabel!
@IBOutlet var latitudeLabel: UILabel!
@IBOutlet var longitudeLabel: UILabel!
@IBOutlet var addressLabel: UILabel!
@IBOutlet var dateLabel: UILabel!
@IBOutlet var imageView: UIImageView!
@IBOutlet var addPhotoLabel: UILabel!
@IBOutlet var imageHeight: NSLayoutConstraint!
//Adding Coin Values
@IBOutlet weak var dollarTextField: UITextField!
@IBOutlet weak var dollarLabel: UILabel!
@IBOutlet weak var halvesTextField: UITextField!
@IBOutlet weak var halvesLabel: UILabel!
@IBOutlet weak var quarterTextField: UITextField!
@IBOutlet weak var quarterLabel: UILabel!
@IBOutlet weak var dimeTextField: UITextField!
@IBOutlet weak var dimeLabel: UILabel!
@IBOutlet weak var nickelTextField: UITextField!
@IBOutlet weak var nickelLabel: UILabel!
@IBOutlet weak var pennyTextField: UITextField!
@IBOutlet weak var pennyLabel: UILabel!
@IBOutlet weak var numberOfCoinsLabel: UILabel!
@IBOutlet weak var cashLabel: UILabel!
var coordinate = CLLocationCoordinate2D(
latitude: 0,
longitude: 0)
var placemark: CLPlacemark?
var categoryName = "No Category"
var managedObjectContext: NSManagedObjectContext!
var date = Date()
var descriptionText = ""
var image: UIImage?
var observer: Any!
var locationToEdit: Location? {
didSet {
if let location = locationToEdit {
descriptionText = location.locationDescription
categoryName = location.category
date = location.date
coordinate = CLLocationCoordinate2DMake(
location.latitude,
location.longitude)
placemark = location.placemark
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
if let location = locationToEdit {
title = "Edit Location"
if location.hasPhoto {
if let theImage = location.photoImage {
show(image: theImage)
}
}
}
descriptionTextView.text = descriptionText
categoryLabel.text = categoryName
// dollarTextField.text = dollarAmount
//add entities for coins
latitudeLabel.text = String(
format: "%.8f",
coordinate.latitude)
longitudeLabel.text = String(
format: "%.8f",
coordinate.longitude)
if let placemark = placemark {
addressLabel.text = string(from: placemark)
} else {
addressLabel.text = "No Address Found"
}
dateLabel.text = format(date: date)
// Hide keyboard
let gestureRecognizer = UITapGestureRecognizer(
target: self,
action: #selector(hideKeyboard))
gestureRecognizer.cancelsTouchesInView = false
tableView.addGestureRecognizer(gestureRecognizer)
listenForBackgroundNotification()
}
deinit {
print("*** deinit \(self)")
NotificationCenter.default.removeObserver(observer!)
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "PickCategory" {
let controller = segue.destination as! CategoryPickerViewController
controller.selectedCategoryName = categoryName
}
}
// MARK: - Actions
@IBAction func done() {
guard let mainView = navigationController?.parent?.view
else { return }
let hudView = HudView.hud(inView: mainView, animated: true)
let location: Location
if let temp = locationToEdit {
hudView.text = "Updated"
location = temp
} else {
hudView.text = "Tagged"
location = Location(context: managedObjectContext)
location.photoID = nil
}
location.locationDescription = descriptionTextView.text
location.category = categoryName
location.latitude = coordinate.latitude
location.longitude = coordinate.longitude
location.date = date
location.placemark = placemark
// Save coin values from text fields
location.dollarAmount = Double(dollarTextField.text ?? "0") ?? 0
location.halvesAmount = Double(halvesTextField.text ?? "0") ?? 0
location.quarterAmount = Double(quarterTextField.text ?? "0") ?? 0
location.dimeAmount = Double(dimeTextField.text ?? "0") ?? 0
location.nickelAmount = Double(nickelTextField.text ?? "0") ?? 0
location.pennyAmount = Double(pennyTextField.text ?? "0") ?? 0
// Save image
if let image = image {
if !location.hasPhoto {
location.photoID = Location.nextPhotoID() as NSNumber
}
if let data = image.jpegData(compressionQuality: 0.5) {
do {
try data.write(to: location.photoURL, options: .atomic)
} catch {
print("Error writing file: \(error)")
}
}
}
do {
try managedObjectContext.save()
afterDelay(0.6) {
hudView.hide()
self.navigationController?.popViewController(
animated: true)
}
} catch {
fatalCoreDataError(error)
}
}
@IBAction func cancel() {
navigationController?.popViewController(animated: true)
}
@IBAction func categoryPickerDidPickCategory(
_ segue: UIStoryboardSegue
) {
let controller = segue.source as! CategoryPickerViewController
categoryName = controller.selectedCategoryName
categoryLabel.text = categoryName
}
@IBAction func calculateButtonPressed(_ sender: UIButton) {
if let inputText = dollarTextField.text, let dollarAmount = Double(inputText) {
let result = dollarAmount * 1.00
dollarLabel.text = String(format: "$%.2f", result)
} else {
dollarLabel.text = "0"
dollarTextField.text = "0"
}
if let inputText = halvesTextField.text, let halvesAmount = Double(inputText) {
let result = halvesAmount * 0.50
halvesLabel.text = String(format: "$%.2f", result)
} else {
halvesLabel.text = "0"
halvesTextField.text = "0"
}
if let inputText = quarterTextField.text, let quarterAmount = Double(inputText) {
let result = quarterAmount * 0.25
quarterLabel.text = String(format: "$%.2f", result)
} else {
quarterLabel.text = "0"
quarterTextField.text = "0"
}
if let inputText = dimeTextField.text, let dimeAmount = Double(inputText) {
let result = dimeAmount * 0.10
dimeLabel.text = String(format: "$%.2f", result)
} else {
dimeLabel.text = "0"
dimeTextField.text = "0"
}
if let inputText = nickelTextField.text, let nickelAmount = Double(inputText) {
let result = nickelAmount * 0.05
nickelLabel.text = String(format: "$%.2f", result)
} else {
nickelLabel.text = "0"
nickelTextField.text = "0"
}
if let inputText = pennyTextField.text, let pennyAmount = Double(inputText) {
let result = pennyAmount * 0.01
pennyLabel.text = String(format: "$%.2f", result)
} else {
pennyLabel.text = "0"
pennyTextField.text = "0"
}
guard let dollarCount = Int(dollarTextField.text ?? "0"),
let halvesCount = Int(halvesTextField.text ?? "0"),
let quarterCount = Int(quarterTextField.text ?? "0"),
let dimeCount = Int(dimeTextField.text ?? "0"),
let nickelCount = Int(nickelTextField.text ?? "0"),
let pennyCount = Int(pennyTextField.text ?? "0") else {
return
}
let totalCoins =
dollarCount +
halvesCount +
quarterCount +
dimeCount +
nickelCount +
pennyCount
numberOfCoinsLabel.text = "\(totalCoins)"
// Calculate dollar amount
let dollarAmount = Double(dollarTextField.text ?? "") ?? 1
let halvesAmount = (Double(halvesTextField.text ?? "") ?? 0.0) * 0.50
let quarterAmount = (Double(quarterTextField.text ?? "") ?? 0.0) * 0.25
let dimeAmount = (Double(dimeTextField.text ?? "") ?? 0.0) * 0.10
let nickelAmount = (Double(nickelTextField.text ?? "") ?? 0.0) * 0.05
let pennyAmount = (Double(pennyTextField.text ?? "") ?? 0.0) * 0.01
// Update labels
dollarLabel.text = String(format: "$%.2f", dollarAmount)
halvesLabel.text = String(format: "$%.2f", halvesAmount)
quarterLabel.text = String(format: "$%.2f", quarterAmount)
dimeLabel.text = String(format: "$%.2f", dimeAmount)
nickelLabel.text = String(format: "$%.2f", nickelAmount)
pennyLabel.text = String(format: "$%.2f", pennyAmount)
// Calculate total cash amount
let totalCash =
dollarAmount +
halvesAmount +
quarterAmount +
dimeAmount +
nickelAmount +
pennyAmount
cashLabel.text = String(format: "$%.2f", totalCash)
}
// MARK: - Helper Methods
func string(from placemark: CLPlacemark) -> String {
var line = ""
line.add(text: placemark.subThoroughfare)
line.add(text: placemark.thoroughfare, separatedBy: " ")
line.add(text: placemark.locality, separatedBy: ", ")
line.add(text: placemark.administrativeArea, separatedBy: ",")
line.add(text: placemark.postalCode, separatedBy: " ")
line.add(text: placemark.country, separatedBy: ", ")
return line
}
func format(date: Date) -> String {
return dateFormatter.string(from: date)
}
@objc func hideKeyboard(
_ gestureRecognizer: UIGestureRecognizer
) {
let point = gestureRecognizer.location(in: tableView)
let indexPath = tableView.indexPathForRow(at: point)
if indexPath != nil && indexPath!.section == 0 &&
indexPath!.row == 0 {
return
}
descriptionTextView.resignFirstResponder()
}
func show(image: UIImage) {
imageView.image = image
imageView.isHidden = false
addPhotoLabel.text = ""
imageHeight.constant = 260
tableView.reloadData()
}
func listenForBackgroundNotification() {
observer = NotificationCenter.default.addObserver(
forName: UIApplication.didEnterBackgroundNotification,
object: nil,
queue: OperationQueue.main) { [weak self] _ in
if let weakSelf = self {
if weakSelf.presentedViewController != nil {
weakSelf.dismiss(animated: false, completion: nil)
}
weakSelf.descriptionTextView.resignFirstResponder()
}
}
}
// MARK: - Table View Delegates
override func tableView(
_ tableView: UITableView,
willSelectRowAt indexPath: IndexPath
) -> IndexPath? {
if indexPath.section == 0 || indexPath.section == 1 {
return indexPath
} else {
return nil
}
}
override func tableView(
_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath
) {
if indexPath.section == 0 && indexPath.row == 0 {
descriptionTextView.becomeFirstResponder()
} else if indexPath.section == 1 && indexPath.row == 0 {
tableView.deselectRow(at: indexPath, animated: true)
pickPhoto()
}
}
}
extension LocationDetailsViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
// MARK: - Image Helper Methods
func takePhotoWithCamera() {
let imagePicker = UIImagePickerController()
imagePicker.sourceType = .camera
imagePicker.delegate = self
imagePicker.allowsEditing = true
present(imagePicker, animated: true, completion: nil)
}
func choosePhotoFromLibrary() {
let imagePicker = UIImagePickerController()
imagePicker.sourceType = .photoLibrary
imagePicker.delegate = self
imagePicker.allowsEditing = true
present(imagePicker, animated: true, completion: nil)
}
func pickPhoto() {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
showPhotoMenu()
} else {
choosePhotoFromLibrary()
}
}
func showPhotoMenu() {
let alert = UIAlertController(
title: nil,
message: nil,
preferredStyle: .actionSheet)
let actCancel = UIAlertAction(
title: "Cancel",
style: .cancel,
handler: nil)
alert.addAction(actCancel)
let actPhoto = UIAlertAction(
title: "Take Photo",
style: .default) { _ in
self.takePhotoWithCamera()
}
alert.addAction(actPhoto)
let actLibrary = UIAlertAction(
title: "Choose From Library",
style: .default) { _ in
self.choosePhotoFromLibrary()
}
alert.addAction(actLibrary)
present(alert, animated: true, completion: nil)
}
// MARK: - Image Picker Delegates
func imagePickerController(
_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]
) {
image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage
if let theImage = image {
show(image: theImage)
}
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(
_ picker: UIImagePickerController
) {
dismiss(animated: true, completion: nil)
}
}
I’am trying to save using the done(), no crashes/no saving to core data. What am I missing. Thank You