UIKit Apprentice, MyLocations core data

Trying to add to the tutorial and save from a textfield and label to core data.

  1. 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