1

I have been developing an app with cloud/server data source. So naturally the process is one thing at a time. So at present, to fill my tables, I query the server which returns an array. The array contains urls to images and then from the urls I load the images using SDWebImage.

Now I am entering the stage of development where I need to implement Core Data for all the data in my tables (i.e. texts and images). So far I am considering the following approaches:

  • I can load the array from the server into core data (imagine properties as: firstName, lastName, photoUrl, shortBio) and then pass the photo url from core data to SDWebImage to display the image in the table cells. OR
  • I can load the array and the image into Core Data (i.e. load the array into core data in the background and then for each row, load the image into core data)

Of course the point here is that if I use SDWebImage it will save the image in its own caching system, which from my limited understanding may or may not be entirely consistent with what is in core data. On the other hand I don't understand core data enough to know if it handles saving images well in terms of performance (i.e. knows it's an image and therefore handle the file linking).

So What is the best way to do this? Can SDWebImage work in harmony with Core Data? Or is SDWebImage redundant since core data is good enough all by itself?

Another thing to note is that presently, my data loads from server immediately and then the images come as SDWebImage loads each into its UIImageView. This may not be a problem with Core Data since ideally the image will be in the local DB. Any thoughts?

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
Katedral Pillon
  • 14,534
  • 25
  • 99
  • 199
  • 2
    Disgruntled person who down voted and ask to close, do you have a thing for me? – Katedral Pillon Sep 10 '14 at 16:14
  • @Almo was that so hard? I just think it's respectful and helpful to explain why you vote down or to close. Had I not posted the facetious comment you would not have provided an explanation. – Katedral Pillon Sep 10 '14 at 16:48
  • 5
    Also notice that your reasoning is a logical fallacy. Note that the question is about whether both or one or the other approach is sufficient for solving the problem of caching images. The question is asking for a factual answer: truth table with two inputs. To say it's a matter of opinion is to in fact concede that "any of the choices is sufficient". So really you misread the question. But thanks for pointing out that they are all equivalent. A further explanation for why the choices are equal would be nice. But here again is the importance of explaining a vote to close. – Katedral Pillon Sep 10 '14 at 16:58
  • 3
    StackOverflow should really make it mendatory for people to provide explanations for their down votes or votes to close. This is a good example of why explanations are required. – Konsol Labapen Sep 10 '14 at 17:16
  • 3
    "mendatory" is great! Thanks for that. One more way to mend the system. – Mundi Sep 10 '14 at 17:17
  • Manditory explanations for downvotes would kill one means of feedback the site has. There are thousands of questions to deal with, and we don't have time to type something for every question or answer that deserves a downvote. – Almo Sep 10 '14 at 17:27

2 Answers2

3

Based on your question and comments, it seems you are trying to locally cache images that were retrieved through an HTTP request.

The URL loading system is already caching the images. There is no need to implement another layer of caching on top of that, wether it be SDWebImage or CoreData. When an HTTP response is received from the server, the server includes "freshness" information that informs the client how long and under what conditions that response is valid. The URL loading system, by default, obeys those rules. You can check the freshness information of responses using a tool like Charles or REDBot. The server is the only party in this conversation that can know how long a response is valid for.

The URL loading system does not, by default, cache to the filesytem - only in-memory. This is easy to change:

cache = [[NSURLCache alloc] initWithMemoryCapacity:(1024*1024*512) diskCapacity:(1024*1024*1024 * 100) diskPath:@"Cache.db"];
[NSURLCache setSharedURLCache:cache];

Or when using NSURLSession:

cache = [[NSURLCache alloc] initWithMemoryCapacity:(1024*1024*512) diskCapacity:(1024*1024*1024 * 100) diskPath:@"Cache.db"];
[sessionConfiguration setURLCache:cache];
session = [NSURLSession sessionWithConfiguration:sessionConfiguration];

Storing image data in Core Data is something in general to be avoided, at least with the NSSQLiteStoreType persistent store. Even small images are large in the SQLite database and cause fragmentation, etc. that impact performance. If you are going to store image data in Core Data, it's preferable to use external storage - either by use Core Data's own external records storage, or by storing image data on the filesystem and referencing it in managed objects by using URLs.

However, if you are using Core Data OR SDWebImage to "cache" images, you are ignoring the freshness information that was returned in the server's response unless you implement your own validation layer - which the URL loading system is already doing for you!

quellish
  • 21,123
  • 4
  • 76
  • 83
  • many thanks for the answer. There is a lot here for me, or anyone else looking, to chew on. One discomfort I have about your response is that SDWebImage is very widely used and highly recommended. And yet you seem to believe it is superfluous for caching images. So that gives me pause a bit. – Katedral Pillon Sep 10 '14 at 21:35
  • Just because something is widely used does not mean it is necessary or useful. Many people use SDWebImage just for it's UIImageView category, and do not really think about what the rest of the library is actually doing. – quellish Sep 10 '14 at 22:00
  • That is indeed correct. Based on digging deeper into your response (links and all) the following conclusion seems to follow: `If caching is all that is needed for a certain table's data source (i.e. model), then Core Data is not necessary; it is in such case sufficient to cache the http response; core data is really for further filtering.` But then lecture 12 of the popular course http://online.stanford.edu/course/developing-ios7-apps-fall-2013 seems to disagree with the aforementioned conclusion, as the professor is using Core Data simply so as not to depend on the server too much. An ideas? – Katedral Pillon Sep 10 '14 at 22:12
  • If you are not familiar with the lecture, all you have to watch is the first 2 to 3 minutes and you will hear him make the argument for using Core Data as local cache. – Katedral Pillon Sep 10 '14 at 22:19
  • His comments about "limiting fetching" from a remote service indicate he is not aware of how the URL loading system handles caching, or that it can persist on the filesystem. When the response is cached, if you make the request again it will be served from the cache until it is invalidated rather than "fetching from the server". I will refer you back to my answer. – quellish Sep 11 '14 at 00:05
2

Regardless of the question semantics, I think you need some more hard information to inform your decision.

It would be useful for you to know that storing large images (larger than, say, thumbnails) is not recommended and will lead to performance issues. Core Data has an option for large data where you can check "Store in External Record File". Alternatively, you can administer your own cache data (in this way you can flexibly update the images via download on a per-need basis on each device sharing the same data). The accepted best practice is to only store the image URL in Core Data (typically relative to the application directory) and handle the file storage / display separately.

I do not know SDWebImage, but this might provide some of the functionality that you need in the light of the above.

I hope this helps you make your decision about the data architecture.

Mundi
  • 79,884
  • 17
  • 117
  • 140
  • Thanks for the reply. The performance issue you mention, is it only if I do not check `Store in External Record File`? Or is the issue present as long as the image is larger than thumbnail - regardless of whether I check external storage? – Katedral Pillon Sep 10 '14 at 17:33
  • I guess external record should take care of the db performance, but only tests with your own data will give a conclusive answer. – Mundi Sep 10 '14 at 17:44
  • The other response prove to be extremely difficulty to implement. Theoretically it sounds great, but this one is easier to work with, at least at my junior level. – Katedral Pillon Sep 16 '14 at 00:55