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

Comments

Projects
None yet
3 participants
@osolano

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

This comment has been minimized.

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

This comment has been minimized.

osolano commented Oct 13, 2016

This helped! Closing

@osolano osolano closed this Oct 13, 2016

@osolano osolano reopened this Oct 21, 2016

@osolano

This comment has been minimized.

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

This comment has been minimized.

Owner

Krisiacik commented Oct 21, 2016

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

This comment has been minimized.

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

This comment has been minimized.

Owner

Krisiacik commented Oct 21, 2016

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

@osolano

This comment has been minimized.

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

This comment has been minimized.

Owner

Krisiacik commented Oct 26, 2016

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

@zfoltin

This comment has been minimized.

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