Finding Directories in iOS

I created a Utilities singleton to keep things I refer to often. These are the methods I use for referring to directories.


#pragma mark - Application's Documents directory
// Directory locations
+ (NSString *)applicationCachesDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
}

+ (NSString *)applicationDocumentsDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

+ (NSString *)applicationLibraryDirectory {
    
    return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
}

Here’s one for retrieving the contents of a file stored in the Caches Directory. Notice how it uses [self applicationCachesDirectory] to get the location of the directory.


// Cached files for results
+ (NSString *)cachedFilePath:(NSString *)fileName {
    NSString *pathComponent = [NSString stringWithFormat:@"%@.txt",fileName];
    NSString *filePath = [[self applicationCachesDirectory] stringByAppendingPathComponent:pathComponent];
    return filePath;
}

If I want to store the results in the Documents directory, I’ll use this to construct the path.


        NSString *resultsFilePath = [ [Utilities applicationDocumentsDirectory] stringByAppendingPathComponent:[self formattedHTMLFileName:@"Results"] ];

Here’s a slightly more complicated example where I retrieve the contents of a cached file. Note that it makes use of cachedFilePath:fileName as described above.


+ (NSString *)cachedFileContents:(NSString *)fileName {
    NSStringEncoding encoding; NSError* error = nil;
    NSString *text = [NSString stringWithContentsOfFile:[self cachedFilePath:fileName] usedEncoding:&encoding error:&error];
    return text;
}

Here’s another example. This time I’m loading a string with the contents of the FullResults file.


 NSStringEncoding encoding;
    NSError* error = nil;
    NSString *resultsText = [NSString stringWithContentsOfFile:[Utilities cachedFilePath:@"FullResults"] usedEncoding:&encoding error:&error];

Rename a bunch of files

Photoshop mangles file names when you run batch saves on them, so I’ve had to rename a bunch of files after processing. Here’s what I do from the shell prompt to rename a bunch of files in a PictsFolder.

Create a file called rename.sh


#!/bin/bash
cd /Users/gmiller/Desktop/PictsFolder
mv 1.png a.png
mv 2.png b.png
exit

chmod it to be executable. I use chmod 777 rename.sh because I’m lazy. Then run it from the command line.

jscarry$ /Users/gmiller/Files/renamePicts.sh
Be sure to escape special characters like spaces in your file names.

e.g. File\ Name\ With\ Spaces.png

JPEG Image Compression

We’ve made a bunch of games for iPads and based on reading the docs made all of our images PNGs. But that resulted in huge file sizes, especially for games that use photos. So we switched to JPEGs for the content. Buttons are still PNGs.

In our first batch of games we used PhotoShop at 30% quality setting. The pictures are OK looking but you can see some artifacts, especially when there are large areas of the same color, like skies. For our current game, we experimented with ImageOptim. The new images are virtually indistinguishable from the originals. This is significantly smaller than Photoshop—but not as small as you can get with a lower quality setting in Photoshop. Since there are no sounds in this game, we’ll probably go with ImageOptim.

Here are some stats for 3673 pictures at 644×498.


Originals:         1,140.0 MB 
ImageOptim 80%       249.6 MB
ImageOptim 2nd Pass  238.9 MB

Photoshop 80%        323.9 MB
Photoshop 50%        249.8 MB
50% with ImageOptim  241.3 MB
50% with 2x IO       241.0 MB
Photoshop 30%        166.7 MB

ImageOptim only has an 80% setting and running two passes gets you as small as you are going to get. I think, but can’t verify, that IgageOptim on JPEGs doesn’t do any compression per se. It just strips out and cleans up overhead and doesn’t affect the image quality. In other words, it’s lossless compression.

UPDATE: I tried this on a bunch of PNGs and got less dramatic, but still significant, results.


438 Images: 98.9 MB --> 81.5 MB = 18%
 68 Images: 19.3 MB ==> 15.8 MB = 18%

I also compressed a file with a mix of JPEGs, PNGs, and PDFs.


145 Images: 65.9 --> 38.8 MB = 39%

How to center an image with a caption.

E6-B

Let’s check that wind correction angle.

Use this code:


<div class="centered"><img class="centered" src="/images/696866-spock.jpg" alt="E6-B" /><p class="caption">Let’s check that wind correction angle.</p>
</div>

Note that the whole thing is wrapped in a div and the caption is in a paragraph.

The CSS for the classes is:

Image centering in a paragraph with padding.


img.centered {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

Caption


.caption {
  text-align: center;
  margin-top: -4px;
  font-style: italic;
  font-size: 80%;
}

Using % in NSString

It probably says this somewhere, but I missed it. I’m writing results to the screen and to a file and it works fine with this code for my table headers:


tableHeader = @"<table width='100%' border='1'><tr><th colspan='2'>Presentations</th></tr>";

I wanted to adjust the colspan depending on the number of presentations for different conditions. So I put the code into an NSString like so:


NSInteger numColumns = 6;
tableHeader = [NSString stringWithFormat:@"<table width='100%' border='1'><tr><th colspan='%d'>Presentations</th></tr>", numColumns];

The table no longer takes up the whole page. I tried escaping the 100% like you normally do \% but that didn’t do anything. The correct way to escape a percent sign is to double it. e.g. %%

So now you know.