Loading UIImages to collectionView from local storage is very slow
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
add a comment |
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
1
Something tells me thatlet 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
add a comment |
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
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
swift macos asynchronous uicollectionview
edited Nov 14 '18 at 21:29
RX9
6112723
6112723
asked Nov 14 '18 at 17:25
user10241612user10241612
53
53
1
Something tells me thatlet 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
add a comment |
1
Something tells me thatlet 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
add a comment |
1 Answer
1
active
oldest
votes
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
Thank you a lot. I am going to implement this today.
– user10241612
Nov 15 '18 at 7:59
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
Thank you a lot. I am going to implement this today.
– user10241612
Nov 15 '18 at 7:59
add a comment |
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
Thank you a lot. I am going to implement this today.
– user10241612
Nov 15 '18 at 7:59
add a comment |
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
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
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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