David Sanford David Sanford - 3 months ago 16
Swift Question

Getting a nil error with UITextView

I am creating an app that will have several segments of it that will connect to parse, so I thought I would try to create a custom Class for the parse functions.

This address book tab is the first attempt.

I hit a snag with something that I thought would be so simple, but after 10 hours of research, I am turning here.

Here is the ViewController

var addressUUID = NSUUID().UUIDString


class AddViewController : UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {


@IBOutlet weak var addressImage : UIImageView!
@IBOutlet weak var nameField : UITextField!
@IBOutlet weak var lastNameField : UITextField!
@IBOutlet weak var phoneField : UITextField!
@IBOutlet weak var emailField : UITextField!
@IBOutlet weak var addressCityField : UITextField!
@IBOutlet weak var addressCountryField : UITextField!

@IBOutlet weak var nameFieldLabel : UILabel!
@IBOutlet weak var lastNameFieldLabel : UILabel!
@IBOutlet weak var phoneFieldLabel : UILabel!
@IBOutlet weak var emailFieldLabel : UILabel!
@IBOutlet weak var addressCityFieldLabel : UILabel!
@IBOutlet weak var addressCountryFieldLabel : UILabel!
@IBOutlet weak var doneButton: UIButton!

@IBOutlet weak var scrollView: UIScrollView!
var scrollViewHeight : CGFloat = 0

var person : Person?
var parse : ParseData?
// creating frame for keyboard to force scroll view up
var keyboard = CGRect()

@IBAction func addButtonPressed(sender : UIButton) {
//NSLog("Button pressed")


print ("\(nameField.text)")


parse = ParseData.init(firstName: nameField.text!)

// Saves data to Parse class, regardless of if new or updated record
do {

try parse!.setFirstName(nameField.text!)
try parse!.setLastName(lastNameField.text!)
try parse!.setPhone(phoneField.text!)
try parse!.setEmail(emailField.text!)
try parse!.setAddressCity(addressCityField.text!)
try parse!.setAddressCountry(addressCountryField.text!)
try parse!.setAddressImage(addressImage.image!)
try parse!.setUUID(addressUUID)

} catch let error as PersonValidationError {
var errorMsg = ""

switch(error) {
case .InvalidFirstName:
errorMsg = "Invalid first name"
case .InvalidAddressCity:
errorMsg = "Invalid City"
case .InvalidEmail:
errorMsg = "Invalid email address"
case .InvalidPhone:
errorMsg = "Invalid phone number"
case .InvalidAddressImage:
errorMsg = "Invalid Image"
case .InvalidAddressCountry:
errorMsg = "Invalid Country"
}
let alert = UIAlertController(title: "Error", message: errorMsg, preferredStyle: .Alert)

alert.addAction(UIAlertAction(title: "Okay", style: .Default, handler: nil))

self.presentViewController(alert, animated: true, completion: nil)
} catch {

}

if person == nil
{
parse!.saveAddressToParse()
} else {
parse!.updateAddressToParse()
}


As noted, the error is the first line of "try"

The strange thing is the data sent to the Person class works fine.
Also, when I had the Parse functions on this VC, it worked (albeit with a modified code)

Here is the class ParseData

import Foundation
import Parse


enum ParseValidationError : ErrorType {
case InvalidFirstName
case InvalidAddressCity
case InvalidPhone
case InvalidEmail
case InvalidAddressCountry
case InvalidAddressImage
}

// class ParseData : PFObject, PFSubclassing

class ParseData : PFObject, PFSubclassing
{
private(set) var firstName : String?
private(set) var lastName : String?
private(set) var addressCity : String?
private(set) var addressCountry : String?
private(set) var phone : String?
private(set) var email : String?
private(set) var uuid : String?
private(set) var addressImageFile : UIImage?

var person : Person?

init?(firstName fn: String) {
super.init()
do {
try setFirstName(fn)
} catch {
return nil
}

}
static func parseClassName() -> String {
return "ParseData"
}

func saveAddressToParse () {

print ("saveToParse function begins")

let savedAddressObject = PFObject(className: "addressBook")

savedAddressObject["firstName"] = self.firstName!
savedAddressObject["lastName"] = self.lastName!
savedAddressObject["phone"] = self.phone!
savedAddressObject["email"] = self.email!
savedAddressObject["addressCity"] = self.addressCity!
savedAddressObject["addressCountry"] = self.addressCountry!
savedAddressObject["username"] = PFUser.currentUser()!.username
savedAddressObject["uuid"] = addressUUID
savedAddressObject["entryFrom"] = "Divelog New"

let addressBookImageData = UIImageJPEGRepresentation(self.addressImageFile!, 0.5)
let addressBookImageFile = PFFile(name: "addressBookImage.jpg", data: addressBookImageData!)
savedAddressObject ["addressBookImage"] = addressBookImageFile

savedAddressObject.pinInBackground()
savedAddressObject.saveEventually()
}


func updateAddressToParse () {

print ("updateToParse function begins")

let updateAddressQuery = PFQuery(className: "addressBook")
updateAddressQuery.whereKey("uuid", equalTo: person!.uuid!)
updateAddressQuery.getFirstObjectInBackgroundWithBlock {(objects: PFObject?, error: NSError?) -> Void in

if error == nil {

if let updateAddressObject = objects {

updateAddressObject.setValue(self.firstName!, forKey: "firstName")
updateAddressObject.setValue(self.lastName!, forKey: "lastName")
updateAddressObject.setValue(self.phone!, forKey: "phone")
updateAddressObject.setValue(self.email!, forKey: "email")
updateAddressObject.setValue(self.addressCity!, forKey: "addressCity")
updateAddressObject.setValue(self.addressCountry!, forKey: "addressCountry")
updateAddressObject.setValue("Divelog Update", forKey: "entryFrom")

let addressBookImageData = UIImageJPEGRepresentation(self.addressImageFile!, 0.5)
let addressBookImageFile = PFFile(name: "addressImage.jpg", data: addressBookImageData!)
updateAddressObject.setValue(addressBookImageFile!, forKey: "addressBookImage")

updateAddressObject.pinInBackground()
updateAddressObject.saveEventually()
}
}
}
}

func setFirstName(fn : String) throws {
firstName = fn
}

func setLastName(ln : String) throws {
lastName = ln
}

func setPhone (ph : String) throws {
phone = ph
}

func setEmail (em : String) throws {
email = em
}

func setAddressCity(adc : String) throws {
addressCity = adc
}

func setAddressCountry(ad : String) throws {
addressCountry = ad
}

func setAddressImage(ai : UIImage) throws {
addressImageFile = ai
}

func setUUID(ui : String) throws {
uuid = ui
}

}


Needed to add to the AppDelete:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {


ParseData.registerSubclass()

Parse.enableLocalDatastore()


The above is the corrected answer and it works fine.

Answer

I cant see, where you create an instance of ParseData. I see, that you declare it with

var parse : ParseData?

and then in addButtonPressed you use it. But in between, where is the code that defines it? Something like:

parse = ParseData()
Comments