When releasing to the application store someone wrote in an offhand comment that you need to avoid embedding your images into the executable.
How do you do that?
I've seen code in various books that suggests encoding images as C byte array constants in the source code, and I can say that that's definitely a bad idea for reasons ranging from inefficient pixel formats to unsalvageable memory. That would qualify as "in the executable file" in a way that bundle resources don't, since bundle resources are packaged alongside the executable rather than within it.
I am not sure if I get you correctly, but maybe he meant accidentally adding image files to the Compile Sources category in your build target? This usually does not happen with images, but i have seen it happening with js files.
Perhaps they meant that you should only include images in the bundle that are essential.
The bundle is essentially read-only so you cannot remove an image from the device that is in the bundle. Therefore placing lots of example images that you expect a user to remove/not want is not a good idea because when the user deletes the images from inside your app no space on the device will be reclaimed.
Of course it is fine to place images in the bundle just make sure that they are required and are not taking up unnecessary space that the user cannot reclaim.
Related
I have a Default.png which includes a version number on it. Every time I update my app, I have to change it both in the lite and full version's default.png and default#2x.png. Hassle, no?
I'm pretty sure I've been going about this the wrong way. What should I do instead? (I would like to show a version number on launch, not just nix it altogether.)
Compile-Time Image Compositing
If your logo doesn't need to change other than the version number, then you can use your graphics library of choice at compile-time to refactor the png. Pseudo code below:
Pseudo-Code:
UpdateLogo(String logoName, String version)
{
WidgetImage MyLogo(logoName + ".png");
MyLogo.DrawText(800, 650, version);
MyLogo.Write(logoName + "Final.png");
}
UpdateLogo("Logo.png", "Version 1.0.0");
Compile that program and keep it around as a custom build tool. Then whenever you need to build your application you can compile Logo.png into LogoFinal.png. If you need help using XCode or other tools to generate image files I suggest you search for image manipulation tools separately from "dynamic versioning".
Ideally your version string will use constants defined in an easily-editable table or controlled by your build system. At the very least it will save you from opening up Photoshop every time you need to build your app.
For Display in a Running Application
You should be using a font to draw the version number on top of the logo. Then you can just include a resource file that is text-based and can be easily updated by automated tools for each build.
Sources
Can you create custom build rules for XCode based on file type?
Apple's Human Interface Guidelines say that the Default.png shouldn't be used as a splash screen; it should represent all of the UI controls the application will show, but without any localizable text or content. (Think of how the the built-in apps like iPod and Contacts behave.)
If you're doing it for a client and they demand it, you can always use the "But the app store might reject it for violating their terms!" argument.
Of course, this doesn't apply if you're not submitting to the Store or if you just don't care. :)
A technical add-on for the people posting above: make sure that any png compositing you're adding to the build process runs before pngcrush executes, so that you're not replacing an optimized image with a script-generated (and likely unoptimized) one. You may also run into weird issues if you try doing it after pngcrush runs (it not displaying), anyway.
I am planning to cache the images from a server and use show it as a sort slide show in my App. I would be asynchronously loading the images.
I have two options:
Either to cache the images as a File and use it whenever necessary.
Cache the images objects in memory and use it when ever necessary and write it in to files when Application quits.
Which one would be better?
Please let me know if you you have any kind of suggestions regarding caching images.
Your second approach has 2 major flaws:
If there's too many images then your application will get low memory warning and you'll have to dispose your images from memory anyway
It's also not a good idea to save all images to file on application quit - it is not guaranteed that your saving code will finish on application exit (e.g. if it takes too long system may just terminate your app and your images will be lost)
I'd suggest saving images to files right after you download them and keep in memory reasonable number of images you need to show without visible delay (loading extra images when required and disposing of unnecessary ones)
I would recommend you the first option. Leaves you more flexibility, e.g. when the data size increases the memory size.
I'd do it like this: Have a NSMutableDictionary with the cached images (as UIImage objects). If the image is not in the cache, look whether it's available as a file. If it's not available as a file, load it, put it into your dictionary and also write it to a file.
As for where to write the files to: you can either use the NSTemporaryDirectory() or create a directory inside your NSLibraryDirectory (use NSSearchPathForDirectoriesInDomains to locate it). The later has the advantage/disadvantage that it will be in the iTunes backup (whether that's an advantage or not depends on the use case). Using the Library directory is Apple's recommended way of storing data that is backed up but does not appear in the iTune's file exchange thingy (Documents directory).
I have started using EGOImageView to handle my caching; it's very versatile and handles the intricacies of caching for you.
It works very well for pulling images via http, you can find it on the EGO developer website here
http://developers.enormego.com/
For image caching solution on iOS platform, you might want to consider SDWebImage framework available at: https://github.com/rs/SDWebImage. It is very easy to integrate and takes care of all your image caching worries.: read more about the working here: https://github.com/rs/SDWebImage#readme
We recently picked this up for our app and it works great.
I'm currently in the process of adapting an existing iOS app into what will be a family of very similar apps (each app instance will probably map to a different country/region).
I'm planning on having a different build target for each of these instances, and the only differences between them should be:
Images (probably just the splashscreen and icons)
Localizations
String variables: base URL for remote services, application ID, support e-mails, etc (possibly half a dozen of such variables)
The code itself should be the same on all apps.
What I'd like to know is what you consider to be best practices for managing a family of applications like this.
Regarding images and localizations (or resources in general), it should simply be a matter of adding/removing the appropriate files from the target (and I guess I can even use the same name for images, in different directories).
The main thing I'm not sure about are the other configuration variables.
I've heard / thought of a few options:
Using preprocessor macros and a main configuration header file with the different URLs, IDs, etc
Loading them from a plist (or similar configuration file) whenever the application launches, and having one such file per target
Creating an empty .sqlite file (this app already uses Core Data) and populating it with the default configuration variables, and having one such file per target
I think the first option is the fastest to get out of hand once I have a few instances of this app, plus I have to recompile every time I change one of these settings.
The third option I'm also not sure about, because I'll be adding entities to my database which don't feel like they belong there, plus it kind of feels like overkill for what will probably be 5-10 settings. I'm also not sure about how to add new settings on updates.
So I'm leaning more towards the second option.
Thoughts? Any alternatives to these?
UPDATE #1:
Regarding the second option, there is also a drawback that those strings (ids, URLs, etc) will be slightly more exposed (i.e. if someone was to open the app and look through the plist) than if they were in the source code. Not that this is that big of a problem, but it's just something to consider.
Update #2:
How about using the app's info.plist directly and storing it there? (thus having an info.plist for each target configuration) Even though originally I was thinking of having a separate plist, and having a "configuration singleton" which would load everything from there on startup, I think it may be simpler to simply have it in the info.plist and then reading it via [[[NSBundle mainBundle] infoDictionary] objectForKey:#"com.example.mykey1"].
I would take the preprocessor option. You can put all your preprocessor in one file/method and it will not be too messy. Like oefe said, change the .sqlite is overkill. And with the multiple plist, you will find yourself dragging things around and doing a lot of error prone actions.
However, I would not make a lot of apps. I would just make one app, let the user select his city at launch. You could also add in-app purchases to let the user add more cities when he wants to.
Your app will be easier to maintain : do you want to upload, change description and screenshots for 10+ apps at each update? I find this painful to do with 1 app...
You will not spam the AppStore : having 10+ more apps in the AppStore with the exact same purpose is ridiculous... That's exactly why Apple made in-app purchases, to avoid that situation.
You will have to find different icon for each of your city : your icon is one of the most important aspect when selling your app on the AppStore. You want it to be as polished as possible. Apple won't allow multiple apps to have the same icon and differentiate icon by putting a label on it is not a good option.
I ended up going for the plist, but instead of creating a new one I used the info.plist file for this, thus no need for extra files per target, as I already needed to have a separate info.plist for each one. I simply load them directly from the bundle with:
[[[NSBundle mainBundle] infoDictionary] objectForKey:#"com.example.mykey1"]
I also used preprocessor (with flags set on the target settings) for a couple of things, but that was mostly for when I wanted to disable/remove completely some parts of the app (e.g. to make sure I got everything I commented out enumeration values and even includes in a couple of places).
I think it's relatively clean and I can easily replicate this for future builds without too much of a mess.
Given that the variation is per country/region, and these variables are strings, why don't you simply treat them as localizable strings, thus reducing the problem to one already solved?
Otherwise, I would go for the plist. Sqlite seems to be an overkill, and is not source-control friendly. And conditional compilation will get messy fast.
Um, I working on a dictionary app and currently trying to add narration for each article. I have about 97000 AAC-files. They are tiny - about 3-5 kilobytes each, but there are so many of them! I don't need SQL DB for access management because filenames are identical to the primary keys, so given the key I will be able to pick a proper sound file from disk and play it (I expect so).
The thing I worry about are issues related to huge number of files. I don't really want to mess up with CoreData.
Will there be any problems if I just add all these files to the application bundle? Will Xcode be angry at me? Will iOS be OK with that?
If not what should I use then? How to handle huge (~100'000) number of files properly?
There is no restriction on the number of files that can be added to your application bundle.
It would be better for you if you can put the files on a folder(say audio) in the app bundle.
Right, this is the problem I have a container (rar,zip) which contains images png's tiffs bmps or jpegs in an order.
The file extension isnt zip or rar though but uses the same compression.
I want to pull out a list of images contained within the file in the numerical order, then depending on the user decision go to the image selected.
I'm not after any code just the high level thought process/logic of how this can be achieved and how it could be achieved on iphone OS.
From what i know of iphone OS it uses a kind of sandbox environment so how would this effect the process as well.
Thanks
You can include the libz framework in your project and write some C to manage zipped data. Or you can use Objective-C wrapper classes others have written.
Your application resides in its own sandbox. You can include zip files in the "bundle", i.e. add them to your project, and copy them to the application's Documents folder to work with them. Or you can copy archived data over the network to the application's Documents folder if you don't want to include files in your project.
I don't think the extension matters so much as the data being in the format you expect it to be.
Everything I wrote above is for zip-ped files. If you're working with rar-formatted archives, you'll need to look at making a static library for the iPhone, perhaps from the UnRAR source code.