Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asynchronous loading images in galleryviewcontroller #59

Closed
osolano opened this issue Oct 6, 2016 · 9 comments · Fixed by #76
Closed

Asynchronous loading images in galleryviewcontroller #59

osolano opened this issue Oct 6, 2016 · 9 comments · Fixed by #76

Comments

@osolano
Copy link

osolano commented Oct 6, 2016

Hello,

I've been having trouble figuring out how to setup the asynchronous loading of images in galleryviewcontroller. Could you provide a snippet that will give me a hint on how to do this?

@Krisiacik
Copy link
Owner

Krisiacik commented Oct 7, 2016

Hi..

here it is. You have to make something a GalleryItemsDatasource and respond to a delegate callback. In that, you return an Enum case with associated value that is the async block that takes the image. This might seem like an overcomplicated solution but it's the only way to let the gallery setup itself properly (it needs to know the type of contents in advance) and then get the images in asynchronous way later ...

func provideGalleryItem(index: Int) -> GalleryItem {

    return GalleryItem.Image(fetchImageBlock: { imageProcessingBlock in

        //prepare your image here ------------
        let image = UIImage()
        //prepare your image here ------------

        imageProcessingBlock(image)
    })
}

You can pass the imageProcessing block as a completion block to some other async operation. The signature of the block is UIImage? -> Void.

@osolano
Copy link
Author

osolano commented Oct 13, 2016

This helped! Closing

@osolano osolano closed this as completed Oct 13, 2016
@osolano osolano reopened this Oct 21, 2016
@osolano
Copy link
Author

osolano commented Oct 21, 2016

Hello, reopening this since after doing some testing it seems that the image isn't being updated when the async call comes back with an image. Basically, when i present the galleryviewcontroller, it first tries to download the image, when the image returns, it calls the imageProcessingBlock. The problem is after it calls it nothing happens. Only after scrolling a bit to the left or to the right does the image come back.

My code looks like this

    func provideGalleryItem(index: Int) -> GalleryItem {

        return GalleryItem.Image { (imageCompletion) in
            let post = self.results.results[index]
            let imageURL = NSURL(string: post.photos[0].deviceImage.url!)!

            PINRemoteImageManager.sharedImageManager().downloadImageWithURL(imageURL, options: .DownloadOptionsNone, progressImage: { (progressResult) in
                if let image = progressResult.image  {
                    imageCompletion(image)
                }
                }, completion: { (completionResult) in
                    if let image = completionResult.image  {
                        imageCompletion(image)
                    }
            })

        }
    }

bug

@Krisiacik
Copy link
Owner

You are calling the imageCompletion(image) block twice in downloadImageWithURL. I think the second occurrence is not necessary and is actually causing the problem.
The completion block of downloadImageWithURL is of no consequence to the image viewer, i think returning nil there is fine.

@zfoltin
Copy link
Collaborator

zfoltin commented Oct 21, 2016

I'd think it's the other way around. From the name progressImage I'd think this block gets called while downloading the image (giving you some progress % probably) and the completion block is called when it's all done. No?
Try to put nil for the progressImage block and only call imageCompletion from the completion block.

@Krisiacik
Copy link
Owner

@zfoltin is right...I missed the "progress" in the problem.

@osolano
Copy link
Author

osolano commented Oct 21, 2016

Thanks @zfoltin @Krisiacik for response. I should've posted a simpler example but both progressImage and imageCompletion return an image.

I tested the issue with just the single completion block and the issue still persists.

    func provideGalleryItem(index: Int) -> GalleryItem {

        return GalleryItem.Image { (imageProcessingBlock) in
            let post = self.results.results[index]
            let imageURL = NSURL(string: post.photos[0].deviceImage.url!)!

            PINRemoteImageManager.sharedImageManager().downloadImageWithURL(imageURL, options: .DownloadOptionsNone, completion: { (completionResult) in
                if let image = completionResult.image  {
                    imageProcessingBlock(image)
                }
            })
        }
    }

@Krisiacik
Copy link
Owner

If you use a different image provider - assets library/ google images/ whatever.., does the issue presist?

@zfoltin
Copy link
Collaborator

zfoltin commented Nov 12, 2016

Hey @osolano

I'm trying to resolve this issue and have a few questions for you.
Are you still experiencing this issue? Are you using the latest v4.0 version of ImageViewer?
I'm not familiar with PINRemoteImageManager which library is it?

I'm not sure, but my suspicion is that PINRemoteImageManager's completion might be called on a background thread. Can you try to wrap the imageProcessingBlock(image) call to execute on the main thread DispatchQueue.main.async { imageProcessingBlock(image) } to see if that resolves the issue?

Many thanks for your help in figuring this out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants