Loading UIImages to collectionView from local storage is very slow












0















I am trying to load some images saved locally (using Disk) to a UICollectionView. Whenever I try to fetch them, the app hangs for about 10 seconds. This tells me I am doing something very wrong.



I am thinking of loading them asynchronously and whenever one of them loads, displaying it first. However, I have them on local storage so why does it take so much time to load them?



The images are imported from the user's iPhone and are not compressed. When loading them, I am loading the whole image (I know it's bad).



Can someone point me towards the right direction?



Here is the first part of the loading process:



   func fetchImage(path: String, imageID: String, completionHandler: @escaping (() throws -> UIImage) -> Void) {
do {
let imagePath = path + imageID + ".png"
let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self)
completionHandler{ return image }
} catch {
completionHandler{ throw AlbumStoreError.CannotFetch("Cannot fetch Image with Error: (error)") }
}
}


here Is the second part



func fetchImages(path: String, completionHandler: @escaping ([UIImage]) -> Void) {
albumsStore.fetchImages(path: path) { (images: () throws -> [UIImage]) in
do{
let images = try images()
DispatchQueue.main.async {
completionHandler(images)
}
} catch {
DispatchQueue.main.async {
completionHandler()
}
}
}
}


here is how it's presented. Basically it returns the whole array and reloads the collection view



func presentImages(response: Collage.Images.Save.Response){
let images = response.images
let viewModel = Collage.Images.ViewModel(images: images)
viewController?.displayImages(viewModel: viewModel) }









share|improve this question




















  • 1





    Something tells me that let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self) is sync, and that's what is taking time.

    – Larme
    Nov 14 '18 at 17:35
















0















I am trying to load some images saved locally (using Disk) to a UICollectionView. Whenever I try to fetch them, the app hangs for about 10 seconds. This tells me I am doing something very wrong.



I am thinking of loading them asynchronously and whenever one of them loads, displaying it first. However, I have them on local storage so why does it take so much time to load them?



The images are imported from the user's iPhone and are not compressed. When loading them, I am loading the whole image (I know it's bad).



Can someone point me towards the right direction?



Here is the first part of the loading process:



   func fetchImage(path: String, imageID: String, completionHandler: @escaping (() throws -> UIImage) -> Void) {
do {
let imagePath = path + imageID + ".png"
let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self)
completionHandler{ return image }
} catch {
completionHandler{ throw AlbumStoreError.CannotFetch("Cannot fetch Image with Error: (error)") }
}
}


here Is the second part



func fetchImages(path: String, completionHandler: @escaping ([UIImage]) -> Void) {
albumsStore.fetchImages(path: path) { (images: () throws -> [UIImage]) in
do{
let images = try images()
DispatchQueue.main.async {
completionHandler(images)
}
} catch {
DispatchQueue.main.async {
completionHandler()
}
}
}
}


here is how it's presented. Basically it returns the whole array and reloads the collection view



func presentImages(response: Collage.Images.Save.Response){
let images = response.images
let viewModel = Collage.Images.ViewModel(images: images)
viewController?.displayImages(viewModel: viewModel) }









share|improve this question




















  • 1





    Something tells me that let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self) is sync, and that's what is taking time.

    – Larme
    Nov 14 '18 at 17:35














0












0








0








I am trying to load some images saved locally (using Disk) to a UICollectionView. Whenever I try to fetch them, the app hangs for about 10 seconds. This tells me I am doing something very wrong.



I am thinking of loading them asynchronously and whenever one of them loads, displaying it first. However, I have them on local storage so why does it take so much time to load them?



The images are imported from the user's iPhone and are not compressed. When loading them, I am loading the whole image (I know it's bad).



Can someone point me towards the right direction?



Here is the first part of the loading process:



   func fetchImage(path: String, imageID: String, completionHandler: @escaping (() throws -> UIImage) -> Void) {
do {
let imagePath = path + imageID + ".png"
let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self)
completionHandler{ return image }
} catch {
completionHandler{ throw AlbumStoreError.CannotFetch("Cannot fetch Image with Error: (error)") }
}
}


here Is the second part



func fetchImages(path: String, completionHandler: @escaping ([UIImage]) -> Void) {
albumsStore.fetchImages(path: path) { (images: () throws -> [UIImage]) in
do{
let images = try images()
DispatchQueue.main.async {
completionHandler(images)
}
} catch {
DispatchQueue.main.async {
completionHandler()
}
}
}
}


here is how it's presented. Basically it returns the whole array and reloads the collection view



func presentImages(response: Collage.Images.Save.Response){
let images = response.images
let viewModel = Collage.Images.ViewModel(images: images)
viewController?.displayImages(viewModel: viewModel) }









share|improve this question
















I am trying to load some images saved locally (using Disk) to a UICollectionView. Whenever I try to fetch them, the app hangs for about 10 seconds. This tells me I am doing something very wrong.



I am thinking of loading them asynchronously and whenever one of them loads, displaying it first. However, I have them on local storage so why does it take so much time to load them?



The images are imported from the user's iPhone and are not compressed. When loading them, I am loading the whole image (I know it's bad).



Can someone point me towards the right direction?



Here is the first part of the loading process:



   func fetchImage(path: String, imageID: String, completionHandler: @escaping (() throws -> UIImage) -> Void) {
do {
let imagePath = path + imageID + ".png"
let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self)
completionHandler{ return image }
} catch {
completionHandler{ throw AlbumStoreError.CannotFetch("Cannot fetch Image with Error: (error)") }
}
}


here Is the second part



func fetchImages(path: String, completionHandler: @escaping ([UIImage]) -> Void) {
albumsStore.fetchImages(path: path) { (images: () throws -> [UIImage]) in
do{
let images = try images()
DispatchQueue.main.async {
completionHandler(images)
}
} catch {
DispatchQueue.main.async {
completionHandler()
}
}
}
}


here is how it's presented. Basically it returns the whole array and reloads the collection view



func presentImages(response: Collage.Images.Save.Response){
let images = response.images
let viewModel = Collage.Images.ViewModel(images: images)
viewController?.displayImages(viewModel: viewModel) }






swift macos asynchronous uicollectionview






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 21:29









RX9

6112723




6112723










asked Nov 14 '18 at 17:25









user10241612user10241612

53




53








  • 1





    Something tells me that let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self) is sync, and that's what is taking time.

    – Larme
    Nov 14 '18 at 17:35














  • 1





    Something tells me that let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self) is sync, and that's what is taking time.

    – Larme
    Nov 14 '18 at 17:35








1




1





Something tells me that let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self) is sync, and that's what is taking time.

– Larme
Nov 14 '18 at 17:35





Something tells me that let image = try Disk.retrieve(imagePath, from: .documents, as: UIImage.self) is sync, and that's what is taking time.

– Larme
Nov 14 '18 at 17:35












1 Answer
1






active

oldest

votes


















0














The problem here is not speed of access to local storage, but rendering of images. You are loading all images from storage and rendering them, even for collection view cells which may be off screen, before displaying anything.



The usual way to handle this is to have the collection view request an image for a cell asynchronously as that cell scrolls in to view. i.e. the view should pull each image from the model, rather than trying to push images from your model into the view.



A complete explanation of how to do this properly is too long for an answer here but there are any number of examples and tutorials on how to do this, just Google asynchronous loading, or lazy loading. Also look at the prefetching API introduced in iOS 10.



See for example https://medium.com/capital-one-tech/smooth-scrolling-in-uitableview-and-uicollectionview-a012045d77f
or Apple's documentation on prefetch: https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching/prefetching_collection_view_data






share|improve this answer
























  • Thank you a lot. I am going to implement this today.

    – user10241612
    Nov 15 '18 at 7:59











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53305699%2floading-uiimages-to-collectionview-from-local-storage-is-very-slow%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














The problem here is not speed of access to local storage, but rendering of images. You are loading all images from storage and rendering them, even for collection view cells which may be off screen, before displaying anything.



The usual way to handle this is to have the collection view request an image for a cell asynchronously as that cell scrolls in to view. i.e. the view should pull each image from the model, rather than trying to push images from your model into the view.



A complete explanation of how to do this properly is too long for an answer here but there are any number of examples and tutorials on how to do this, just Google asynchronous loading, or lazy loading. Also look at the prefetching API introduced in iOS 10.



See for example https://medium.com/capital-one-tech/smooth-scrolling-in-uitableview-and-uicollectionview-a012045d77f
or Apple's documentation on prefetch: https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching/prefetching_collection_view_data






share|improve this answer
























  • Thank you a lot. I am going to implement this today.

    – user10241612
    Nov 15 '18 at 7:59
















0














The problem here is not speed of access to local storage, but rendering of images. You are loading all images from storage and rendering them, even for collection view cells which may be off screen, before displaying anything.



The usual way to handle this is to have the collection view request an image for a cell asynchronously as that cell scrolls in to view. i.e. the view should pull each image from the model, rather than trying to push images from your model into the view.



A complete explanation of how to do this properly is too long for an answer here but there are any number of examples and tutorials on how to do this, just Google asynchronous loading, or lazy loading. Also look at the prefetching API introduced in iOS 10.



See for example https://medium.com/capital-one-tech/smooth-scrolling-in-uitableview-and-uicollectionview-a012045d77f
or Apple's documentation on prefetch: https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching/prefetching_collection_view_data






share|improve this answer
























  • Thank you a lot. I am going to implement this today.

    – user10241612
    Nov 15 '18 at 7:59














0












0








0







The problem here is not speed of access to local storage, but rendering of images. You are loading all images from storage and rendering them, even for collection view cells which may be off screen, before displaying anything.



The usual way to handle this is to have the collection view request an image for a cell asynchronously as that cell scrolls in to view. i.e. the view should pull each image from the model, rather than trying to push images from your model into the view.



A complete explanation of how to do this properly is too long for an answer here but there are any number of examples and tutorials on how to do this, just Google asynchronous loading, or lazy loading. Also look at the prefetching API introduced in iOS 10.



See for example https://medium.com/capital-one-tech/smooth-scrolling-in-uitableview-and-uicollectionview-a012045d77f
or Apple's documentation on prefetch: https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching/prefetching_collection_view_data






share|improve this answer













The problem here is not speed of access to local storage, but rendering of images. You are loading all images from storage and rendering them, even for collection view cells which may be off screen, before displaying anything.



The usual way to handle this is to have the collection view request an image for a cell asynchronously as that cell scrolls in to view. i.e. the view should pull each image from the model, rather than trying to push images from your model into the view.



A complete explanation of how to do this properly is too long for an answer here but there are any number of examples and tutorials on how to do this, just Google asynchronous loading, or lazy loading. Also look at the prefetching API introduced in iOS 10.



See for example https://medium.com/capital-one-tech/smooth-scrolling-in-uitableview-and-uicollectionview-a012045d77f
or Apple's documentation on prefetch: https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching/prefetching_collection_view_data







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 15 '18 at 3:40









DaleDale

1,7361219




1,7361219













  • Thank you a lot. I am going to implement this today.

    – user10241612
    Nov 15 '18 at 7:59



















  • Thank you a lot. I am going to implement this today.

    – user10241612
    Nov 15 '18 at 7:59

















Thank you a lot. I am going to implement this today.

– user10241612
Nov 15 '18 at 7:59





Thank you a lot. I am going to implement this today.

– user10241612
Nov 15 '18 at 7:59




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53305699%2floading-uiimages-to-collectionview-from-local-storage-is-very-slow%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Xamarin.iOS Cant Deploy on Iphone

Glorious Revolution

Dulmage-Mendelsohn matrix decomposition in Python