Calling [UIImage imageWithData:xxx] multiple times - ios

My model comes from Core Data.
My beans have images stored in the model as NSData.
To display my images, I need to do :
[UIImage imageWithData:bean.imageData]
Is it OK if I do that everywhere ? I mean, from view #1 I display image by creating [UIImage imageWithData:], then I go on view #2 where I need to display the same image, but I only pass the bean between the 2 views, so I recreate the UIImage with [UIImage imageWithData].
I am wondering whether it takes too many CPU or memory if I do this... Do I need to manage a cache myself ? I think this might be quite common use case with CoreData so is there a common pattern to handle this ?

imageWithData will not cache your image (as per the docs, the only UIImage method to cache is imageNamed)
Here is an algorithm for caching images, though.

In answer to your question, imageWithData is a bit slow, so, no you probably don't want to do this all over the place. You'd probably want to do some caching for maximum performance (or at least if you're likely to retrieve the same image repeated during a give session with the app). NSCache, like HalR suggested, is a great solution for that.
Furthermore, if the images are huge, you might not want to store them in CoreData at all, but rather store them in your Documents folder, and only store the filename path in CoreData. It's surprising how much slower it is to retrieve the image from your database and then use imageWithData is than it is to use imageWithContentsOfFile. Admittedly, if you're doing cacheing, you'll suffer this performance hit less often, but still, if you're retrieving lots of separate images, the difference is observable. With thumbnail images, though, it's less of an issue. Everyone draws this line in a different place, but for me, if the images are greater than 100kb each (or if I'm doing a lot of image retrieval), I'll use the Documents approach.

Related

Core Data w/ a UIImage property - use a UIImage or NSData?

Been using Core Data for a minute. At some point somewhere in the past, I decided that any image attributes in NSManagedObject subclasses should be instances of NSData. I don't remember exactly what informed that decision, but it's something I learned years ago and have always stuck to since. When I wanted a UIImage, I had a readonly property on my NSManagedObject subclass whose getter would create a UIImage instance from the data using one of the UIImageRepresentation functions.
Now I'm working on a new project, and it occurs to me that Apple's PhotoLocations sample app (Core Data Transformable Attributes) actually uses a UIImage for the persisted property. Why? For simplicity's sake it's certainly easier, no need for that UIImageRepresentation function call.
I'm aware of stuff like "store in external record file" and such, my question isn't about that, or even whether or not images should be in their own entity, related to my original entity - it's simply whether or not I should use UIImage or NSData as the type for a persisted property.
Been hard to figure out what's considered best practice or what the drawback is one way or the other. Any insight would be appreciated.
I always store data in a format that is readable by anyone. It makes for data that is easier to transmit, use in multiple systems, avoids deprecation, etc.
When I store an image I store it in a PNG format instead of UIImage. Why?
UIImage could change.
I may want to upload it to a server.
I may need to read the file on OS X.
I might want to make it transportable later.
When it comes to data, I like to think past just the here and now.

Disk Backed Image Cache for UIImageView in AFNetworking

I'm looking to swap out the AFImageCache used by default in the UIImageView+AFNetworking category for something that's disk based and that can managed a little more accurately (something like NSURLCache). Unfortunately, since UIImageView+AFNetworking is a category and not a subclass, I can't just override af_sharedImageCache with a sublclass of UIImageView OR another category.
Is there any other way to achieve this functionality without copying and pasting most of UIImageView+AFNetworking into my own subclass?
The SDWebImage project provides a similar UIImageView category, but offers both in-memory (using NSCache) and on-disk (using NSFileManager) caching. I'd recommend just using that when you need to cache to disk.
The downside to this implementation is that your network requests won't go through your AFHTTPClient subclass, so depending on what your needs are you might need to implement your own operation queue, authentication, etc. If you're just using it for something basic, like displaying avatar images in a table view, it should be fine.
If that downside bothers you, an alternate idea would be to use SDImageCache (included in the SDWebImage project) to cache the images, and download them yourself using AFNetworking.
Finally, note that AFNetworking has built-in support for NSURLCache, and if you create one it will cache your images to disk. However, image caching is typically used for showing lots of images in a UIScrollView, and NSURLCache doesn't have good enough performance for smooth scrolling.
I have a fork of AFNetworking that includes file cache in the NSCachesDirectory.
You can find it here: https://github.com/andyast/AFNetworking_FileCache
There is a branch that is compatible with V1.3.3 if you need that as well.

How to simply store some files

I'm developing an app which needs to show some logos. These logos are just 8kb PNG files, and I'm just going to handle a little amount of them (10-20 at most). However, these are downloaded from the Internet because they might change. So, what I'm trying to achieve is, making the app to download them (done), storing them into the file system, and only downloading again whenever they change (might be months).
Everyone seems to use Core Data, which in my opinion is something designed for bigger and more complex things, because my files will always have the same name plus don't have relations between them.
Is the file system the way to go? Any good tutorial?
Yes, the file system is probably your best option for this. You say that you've already implemented the downloading. How have you done so? With NSURLConnection? If so, then at some point, you have an NSData object. This has a couple of write... methods you can use to save the data to a file on the filesystem. Be sure to save the files in the right place, as your app is sandboxed and you can't write anywhere you like.
The advantage Core Data brings is efficiency. Using NSFetchedResultsController to display your logos in a tableview gets you optimized object loading and memory management. It will automatically load only the items which can be displayed on one screen, and as the user flicks through the table it will handle releasing items which move offscreen. Implementing that on your own is not a simple task.
If you want to build and display your data without Core Data, you'll probably want to use NSKeyValueCoder, which will allow you to easily write an array or dictionary of objects (including nested arrays, dictionaries, and images).

background-image: to sprite or not to sprite?

Can anyone comment on the decision to use sprites for images or not? I see the following benefits/trade-offs (some of which can be mitigated):
Sprites over individual images
Pros:
Fewer images to manage
Easier to implement themed images
Image swaps (JS/CSS) happen faster (because they do not require additional image loads)
Faster image loads due to fewer HTTP requests
Fewer images to cache (although virtually no difference in overall KB)
Cons:
More background positions to manage
Image payload may be over-inflated (sprite may contain unused images), causing page load may be slower
Slower images loads because they cannot be downloaded synchronously
I don't think there's one definitive answer to this. Opinions will differ according to need and individual preference.
My guideline is to always evaluate the benefit for the end user vs. the benefit for the developers. ie. what is the real value of the work you're doing as a developer.
Reducing the number of HTTP requests is always one of the first things to fix when optimizing a web page. Proper usage of caching can achieve much of the same thing as using sprites does. After all, very often graphics can be cached for a really long time.
There might be more benefit from minimizing scripts and stylesheets rather than adding graphics into a sprite.
Your code for managing sprites might increase complexity and developer overhead, especially as number of developers increases.
Learning proper use of cache-headers and configure your web-server or code properly might often be a more robust way of improving performance in my opinion.
If you've got a decent amount of menu entries in which you want to do roll-over images I'd recommend going to a sprite system as opposed to doing multiple images, all of which need to be downloaded separately. My reasons for so are pretty much inline with what you have mentioned in your post with a couple modifications:
The image swaps wouldn't be done with javascript; most of the sprites I've seen just use the :hover on the link itself within an unordered list.
Depending on the filetype/compression the download of the image file itself will be negligible. Downloading one image as opposed to multiple is generally faster in overall download and load.

Best way to store list of websites on iphone app

By best I mean most efficient.
So don't go on about subjectiveness.
I have a list of websites and I want to store the list on the iphone locally, there must be an URL, title and a small image (like 32x32 max image size). I don't think I should be using CoreData for this. Should I be using a plist?
EDIT:
Efficient's definition I though was obvious. Take up the least amount of room, use lowest memory/CPU. 
Sorry I forgot to say About 10-15 max items. And they just get loaded into a table view when the app first loads or when that view is brought back by a nav controller.  
If you can, leave the images in the resources, and put the url, title and imagename in a pList. Alternatively, you could just create a "Site" class with the three properties, and generate an array of Sites in code. (Or an Array of Dictionaries)
You say not to "go on about subjectiveness" but you don't provide your definition of efficient for this.
You don't specify how many websites you want to store or how you want to use them or what is important to you - storage size, i/o perf, ability to query in specific ways etc.
It doesn't sound like a plist would be a bad fit but I guess my earlier point is just that way you are going to read, write data is generally equally or more important in setting context for questions like this.

Resources