Search code examples
iosswiftcompletion

Return Value in Completion of Function


I have built my own swift framework for running queries on a MySQL database. I am currently developing a chat application in which I need to display an avatar image for each user who is currently chatting.

I am retrieving the user's profile picture URL from my database and then I need to return a UIImage once I get the profile picture URL. I get the error Unexpected non-void return value in void function. Is there a way to make this easier or bypass this error?

This is my full code:

    override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {

    let currentMessage = self.messages[indexPath.row]

    if (currentMessage.senderId == self.senderId) {
        // Current User sent message

        var imageURL: NSURL!

        ConnectionManager.sharedInstance.complexQuery("SELECT profile_picture FROM users WHERE username='\(self.senderId)' ", completion: { (result) in
            if let results = result as? [[String: AnyObject]] {
                for result in results {
                    if let profilePictureURL = result["profile_picture"] {
                        print(profilePictureURL)

                        imageURL = profilePictureURL as! NSURL
                        let imageData = NSData(contentsOfURL: imageURL)
                        let image = UIImage(data: imageData!)

                        // ERROR HERE (line below)
                        return JSQMessagesAvatarImageFactory.avatarImageWithImage(image, diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault))
                    }
                }
            }
        })

    } else {

        var imageURL: NSURL!

        ConnectionManager.sharedInstance.complexQuery("SELECT profile_picture FROM users WHERE username='\(currentMessage.senderId)' ", completion: { (result) in
            if let results = result as? [[String: AnyObject]] {
                for result in results {
                    if let profilePictureURL = result["profile_picture"] {
                        print(profilePictureURL)

                        imageURL = profilePictureURL as! NSURL
                        let imageData = NSData(contentsOfURL: imageURL)
                        let image = UIImage(data: imageData!)

                        // ERROR HERE (line below)
                        return JSQMessagesAvatarImageFactory.avatarImageWithImage(image, diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault))
                    }
                }
            }
        })

    }
}

Solution

  • It seems that ConnectionManager.sharedInstance.complexQuery is an asynchronous function, so the main thread will continue after calling it, there will be nothing left in this context to receive what will be returned so, do what ever you want with the image in the callback function "completion" for example, you may get a reference of your UIImageView and set it's image when you get it, but you need to use another data source delegate method

    collectionView(_:cellForItemAtIndexPath:)
    

    Something like this:

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
        {
            let cell = collectionView.dequeueReusableCellWithReuseIdentifier(YOUR_ID,
                                   forIndexPath: indexPath) as! YourOwnCell
            ConnectionManager.sharedInstance.complexQuery("SELECT profile_picture FROM users WHERE username='\(currentMessage.senderId)' ", completion: { (result) in
                if let results = result as? [[String: AnyObject]] {
                    for result in results {
                        if let profilePictureURL = result["profile_picture"] {
                            print(profilePictureURL)
    
                            imageURL = profilePictureURL as! NSURL
                            let imageData = NSData(contentsOfURL: imageURL)
                            let image = UIImage(data: imageData!)
    
                            // Assuming avatarImageWithImage is returning UIImageView
                            cell.imageView = JSQMessagesAvatarImageFactory.avatarImageWithImage(image, diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault))
                        }
                    }
                }
            })
    
            return cell;
        }