David Sanford
David Sanford

Reputation: 745

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.

Upvotes: 1

Views: 58

Answers (1)

jboi
jboi

Reputation: 11912

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()

Upvotes: 1

Related Questions