user3413380
user3413380

Reputation: 75

cannot convert the expressions type UIImage to type void swift

Im having an issue, I am trying to create a method which accepts a PFObject as a parameter. The PFObject in this case is the facebook picture URL. The method takes the URL and basically converts it into an image. I can get it to work if i just use this block of code without trying to make it into a method, however I would like to create a method out of this so that I dont have to keep repeating myself. When i try to return the users image i keep getting the error cannot convert the expressions type UIImage to type void swift

Here is the code

func downloadFBUserImage(object: PFObject?) -> UIImage? {
var userProfilePhotoURLString = object?.valueForKey("pictureURL") as String?
if userProfilePhotoURLString != nil {
    var pictureURL: NSURL = NSURL(string: userProfilePhotoURLString!)!
    var urlRequest: NSURLRequest = NSURLRequest(URL: pictureURL)
    NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: { (NSURLResponse response, NSData data, NSError error) -> Void in
        if error == nil && data != nil {
            var userProfilePic: UIImage? = UIImage(data: data)
            return userProfilePic
        }


    })
    return nil
}

Upvotes: 1

Views: 2152

Answers (2)

Rob
Rob

Reputation: 437452

The error is reporting that the completionHandler of the sendAsynchronousRequest is defined to pass you the response, data, and error objects, but that it expects that completionHandler, itself, to not return any values. But you're trying to return a value from within that completionHandler closure.

Bottom line, you cannot simply return the UIImage from your function, because you are performing asynchronous method (i.e. the data is returned later even though you return from the function immediately). So, employ asynchronous pattern:

func downloadFBUserImage(object: PFObject?, completionHandler: (UIImage?, NSError?) -> Void) {
    if let userProfilePhotoURLString = object?.valueForKey("pictureURL") as? String {
        let pictureURL = NSURL(string: userProfilePhotoURLString)!
        let urlRequest = NSURLRequest(URL: pictureURL)
        NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue()) { (response, data, error) -> Void in
            if data != nil {
                var userProfilePic = UIImage(data: data)
                completionHandler(userProfilePic, nil)
            } else {
                completionHandler(nil, error)
            }    
        }
    }
}

And you'd call it using the same completion handler pattern that sendAsynchronousRequest does:

downloadFBUserImage(object) { image, error in 
    if image == nil {
        println(error)
    } else {
        // use the image here
    }
}

// but don't try to use asynchronously retrieved image here

Upvotes: 1

rakeshbs
rakeshbs

Reputation: 24572

You cannot return to the completion block like that. The completion block does not have a return parameter. This is why you are getting an error.

For updating the image after download, you can pass in a block along with your downloadFBUserImage function like below.

I used dispatch_async because UI updates have to be done on the main thread.

func downloadFBUserImage(object: PFObject?, completion completionBlock:(UIImage) -> ()) -> (){
    var userProfilePhotoURLString = object?.valueForKey("pictureURL") as String?
    if userProfilePhotoURLString != nil {
        var pictureURL: NSURL = NSURL(string: userProfilePhotoURLString!)!
        var urlRequest: NSURLRequest = NSURLRequest(URL: pictureURL)
        NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: { (NSURLResponse response, NSData data, NSError error) -> Void in
            if error == nil && data != nil {
                if let userProfilePic = UIImage(data: data) {
                   completionBlock(userProfilePic)
                }
            }
        })
    }
}

It can be called like this

func do() {
    downloadFBUserImage(pfObject, completion: { (image) -> () in
            //updateImage
          dispatch_async(dispatch_get_main_queue(), { () -> Void in
              // UI updates
          }
    })
}

Upvotes: 0

Related Questions