Konrad Löchner Konrad Löchner - 1 month ago 20
Swift Question

fatal error: unexpectedly found nil while unwrapping an Optional value when saving NSData to Realm

I want to save an image from an imagePicker with Realm. It works when I choose an picture but not when I don't choose one. I tried to save a standard image when no image is chosen.
But I get the error: fatal error: unexpectedly found nil while unwrapping an Optional value
Location:

class Location: Object{
dynamic var name = ""
dynamic var locationDescription = ""
dynamic var latitude = 0.0
dynamic var longitude = 0.0
dynamic var created = NSDate ()
dynamic var category: Category!
dynamic var imageData: NSData!
}


Add New Entry Controller:

//Image Picker
@IBOutlet var imageView: UIImageView!
let imagePicker = UIImagePickerController()
var selectedImage = UIImage()


@IBAction func loadImage(_ sender: AnyObject) {
imagePicker.allowsEditing = true
imagePicker.sourceType = .photoLibrary
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
present(imagePicker, animated: true, completion: nil)
}
//MARK: - Delegates Image Picker
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : Any])
{
selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage

imageView.image = selectedImage

// Dismiss the picker.
self.dismiss(animated: true, completion: nil)

}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}

func addNewLocation() {
let realm = try! Realm()
//convert image to NSData
let standardData: NSData = UIImagePNGRepresentation(self.imageView.image!)! as NSData
let selctedImageData = NSData(data: UIImageJPEGRepresentation(selectedImage, 0.9)!)
let emptyData = NSData()
// let data = NSData(data: UIImageJPEGRepresentation(selectedImage, 0.9)!)
var data = NSData()

if selctedImageData == emptyData{
data = standardData
}
else{
data = selctedImageData
}

try! realm.write {
let newLocation = Location()


newLocation.name = self.nameTextField.text!
newLocation.category = self.selectedCategory
newLocation.locationDescription = self.descriptionTextField.text
newLocation.latitude = self.selectedAnnotation.coordinate.latitude
newLocation.longitude = self.selectedAnnotation.coordinate.longitude
newLocation.imageData = data


realm.add(newLocation)
self.locations = newLocation
}
}


Edit:
I replaced the Category Model with an string which is generated from an query.

class Location: Object{
...
dynamic var category = ""
dynamic var imageData: NSData!

}

Answer

Your Location model has two properties that are implicitly unwrapped optionals (IUOs): category and imageData. IUOs in Swift are useful when you know that the value might have to store nil, but you can guarantee that it will never be accessed in that state, in ways that the compiler can't imply automatically.

In this case, you're accessing one of these properties before having set its value to something other than nil.

Perhaps self.selectedCategory is nil at the point where it's assigned to the newLocation.category property? It's hard to say given that you didn't include anything related to this value in your sample.

If you can't guarantee that those IUOs will ever be set to something non-nil upon access, I'd suggest that you define them as optionals instead, and handle their nil case specifically.

class Location: Object {
  dynamic var name = ""
  dynamic var locationDescription = ""
  dynamic var latitude = 0.0
  dynamic var longitude = 0.0
  dynamic var created = NSDate()
  dynamic var category: Category?
  dynamic var imageData: NSData?
}