Parse File Query and Swift 1.2 Error - getDataInBackgroundWithBlock

advertisements

I'm trying to query images from Parse and I continue to run into fatal error: unexpectedly found nil while unwrapping optional value. I'm not sure if this has to do with the recent update to Swift and Xcode, so maybe it's on the Parse end or it could certainly be user error.

The only things getDataInBackGroundWithBlock will accept are NSData? and NSError? as optionals. If I try unwrapping them or using other types it won't compile.

The PFQuery returns data as expected. It's only when trying to switch from PFFile to NSData in the getDataInBackGroundWithBlock call that the issue comes up.

The framework is hooked up and running. I've tested it quite a bit.

Here is the call stack:

I've been working on this for over 12 hours straight now. I have looked all over the place and have tried many different things. I don't know anyone who works with Swift or Xcode, your help would go miles and miles.

Here are other threads I have tried to no avail, one is my own:

Unresolvable error with Parse "Get Data In Background With Block"

Parse and Swift 1.2 issue

Parse getDataInBackgroundWithBlock not fetching in order

Swift Image retrieving from Parse sdk - getting crashed

Also Parse docs:

https://www.parse.com/docs/ios_guide#files/iOS (their example was my starting point today)

var photoArray: Array<UIImage> = []

override func viewDidLoad() {
    super.viewDidLoad()

    callPFObjectQuery()

    let testObject = PFObject(className: "QuestionMaster") //testobject
    testObject["foo"] = "bar" //testobject
    testObject.saveInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
        println("Object has been saved.")

    }
} 

func callPFObjectQuery() {

    var finalObjects: [PFObject] = []
    var nsdataObjects: NSData?

    var query: PFQuery = PFQuery(className: "QuestionMaster")
    query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) -> Void in

        for object in objects! {

            let imageFiles = object["questionImage"] as! PFFile!

//error line     imageFiles.getDataInBackgroundWithBlock { (imageData: NSData?, error: NSError?) -> Void in

                    if error == nil {

                        dispatch_async(dispatch_get_main_queue()) {

                            let image = UIImage(data: imageData!)
                            self.photoArray.append(image!)
                            println(self.photoArray[0])

                        }

                    }

                }
            }

        }
    }

Update, November 12, 2015 - Swift 1.2: It's been quite a few months since I've posted this and since it has over 1k views and an answer with no upvotes I felt it best to go back over it and make sure what I selected was indeed correct. I haven't gone through and tested it again but having become very, very familiar(6-8k lines) with the Parse SDK and Swift I feel comfortable with the answer I provided. Uttam Sinha was very close but unwrapping instead of optionals on completion handler in getDataInBackgroundWithBlock won't work. They must be optionals and then unwrapped in the block. Ingouackaz missed the for-loop entirely, but his getDataInBackgroundWithBlock call is correct.

My first attempt was sloppy at best, I was probably frustrated. For those of you that are just beginning, the query right before the data query will complete with an array of PFObject's. Therefore you need to loop through that array, calling getDataInBackgroundWithBlock on each item.

Instead of object["questionImage"] I would probably go with object.valueForKey("questionImage") just to make it more explicit. I would also store the key string "questionImage" as a constant in a file of keys so there would be no need to worry about typos.

I'm not sure about PDF files and Parse. I haven't attempted since that situation. But now I am curious because that would once again make my job easier if possible. I will update once I try again.


This should work with Swift 1.2

file.getDataInBackgroundWithBlock({
                (imageData: NSData?, error: NSError?) -> Void in
                if (error == nil) {
                    let image = UIImage(data:imageData!)
                    println(image)
                }

            })