Wednesday, August 18, 2010

The Funny Thing About Old Code…

The funny thing about old code, and most new code, is that there's usually room for improvement. Shortly after posting NSString appendToFile:usingEncoding:, I realized I could've kill two birds with one stone by adding a category method on NSData and then calling that method from the NSString category method. That way I'd get the functionality on both classes without repeating logic.

Without further ado:

#import <Foundation/Foundation.h>

@interface NSData(MCFileAppend)
- (BOOL)appendToFile:(NSString *)path;
@end

@implementation NSData(MCFileAppend)
- (BOOL)appendToFile:(NSString *)path
{
NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:path];
if (fh == nil)
return [self writeToFile:path atomically:YES];

[fh truncateFileAtOffset:[fh seekToEndOfFile]];

[fh writeData:self];
[fh closeFile];
return YES;
}

@end

#pragma mark -
@interface NSString(MCFileAppend)
- (BOOL)appendToFile:(NSString *)path usingEncoding:(NSStringEncoding)encoding;
@end

@implementation NSString(MCFileAppend)
- (BOOL)appendToFile:(NSString *)path usingEncoding:(NSStringEncoding)encoding
{
NSData *encoded = [self dataUsingEncoding:encoding];
return [encoded appendToFile:path];
}

@end

NSString appendToFile:usingEncoding:

Somewhat frequently I find myself looking in Apple's documentation for a method that I'm sure exists but doesn't show up when I search using the Documentation Viewer in Xcode. Usually in that case, the method does actually exist, but it's not from Apple. Nine out of ten times it means I've got a category method I've used so many times that I've forgotten Apple didn't provide it. The other one out of ten, it's just an indication that I'm slowly growing senile.

When this happens, I try to post the category methods because I figure if I've used the method enough over the years that I though it came from Apple, then other people might be able to use it.

One bit of functionality that I've always been surprised isn't in NSString class is the ability to append the contents of a string onto an existing file. There are methods for creating or replacing a file with the contents of a string, so why not to append the contents onto an existing file? It's a fairly common and very useful task. I've used it for creating application logs, and for other situations where I need to create large files that wouldn't be practical to keep in memory. This is especially nice to have on iOS given the lack of virtual memory.

Here's the category method I use for this. I dug this up yesterday from an older project after searching for it in Apple's documentation. I had to update it a little (it was old enough that it used the old deprecated cString methods.

#import <Foundation/Foundation.h>

@interface NSString(MCFileAppend)
- (BOOL)appendToFile:(NSString *)path usingEncoding:(NSStringEncoding)encoding;
@end


@implementation NSString(MCFileAppend)
- (BOOL)appendToFile:(NSString *)path usingEncoding:(NSStringEncoding)encoding
{
NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:path];
if (fh == nil)
return [self writeToFile:path atomically:YES encoding:encoding error:nil];

[fh truncateFileAtOffset:[fh seekToEndOfFile]];
NSData *encoded = [self dataUsingEncoding:encoding];

if (encoded == nil) return NO;

[fh writeData:encoded];
return YES;
}

@end

Monday, August 16, 2010

Fonts and Font Families

I'm not sure if Apple publishes an official list of supported fonts on iOS, but when working with designers, it's a questions that we developers often need the answer too. Fortunately, it's easy enough to determine it. In fact, the code to generate the list of fonts is the first (and so far only) thing that I've put into Xcode 4's new snippet feature. I'm generally not a big snippet fan. If I use code enough that I feel a need to have it as a snippet, more often than not, it makes sense to encapsulate that functionality generically in a class or category or as part of a common library.

But, there are definitely pieces of code that it's good to have around and that don't really lend themselves to that. Here's my snippet for generating font and family names. Cherish this; I slaved for hours over it. Well, okay… maybe not hours, but it did take me a minute or two to type it in.

for (NSString *family in [UIFont familyNames])
{
NSLog(@"%@", family);
for (NSString *font in [UIFont fontNamesForFamilyName:family])
{
NSLog(@"\t%@", font);
}

}


The result of running this code on the current version of iOS 4 (4.0.2 / 8A400) follows. It's a handy list to provide the designers you work with so they know if they use a font not on the list, you'll have to substitute something else, or whoever's footing the bill will have to cough up potentially expensive font licensing fees.

If you want to see what the fonts actually look like, Michael Critz has put together this nice page that shows them all

Arial Hebrew
ArialHebrew-Bold
ArialHebrew
Zapfino
Zapfino
Oriya Sangam MN
OriyaSangamMN
OriyaSangamMN-Bold
Cochin
Cochin
Cochin-BoldItalic
Cochin-Italic
Cochin-Bold
Baskerville
Baskerville
Baskerville-BoldItalic
Baskerville-Italic
Baskerville-Bold
Verdana
Verdana-Bold
Verdana-BoldItalic
Verdana-Italic
Verdana
Gurmukhi MN
GurmukhiMN
GurmukhiMN-Bold
Palatino
Palatino-BoldItalic
Palatino-Italic
Palatino-Bold
Palatino-Roman
Tamil Sangam MN
TamilSangamMN-Bold
TamilSangamMN
Marker Felt
MarkerFelt-Wide
MarkerFelt-Thin
Courier New
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPS-BoldItalicMT
CourierNewPSMT
Courier
Courier-Oblique
Courier
Courier-Bold
Courier-BoldOblique
DB LCD Temp
DBLCDTempBlack
Trebuchet MS
TrebuchetMS-Italic
Trebuchet-BoldItalic
TrebuchetMS
TrebuchetMS-Bold
Arial Rounded MT Bold
ArialRoundedMTBold
Bangla Sangam MN
BanglaSangamMN
BanglaSangamMN-Bold
Telugu Sangam MN
TeluguSangamMN
TeluguSangamMN-Bold
American Typewriter
AmericanTypewriter-Bold
AmericanTypewriter
Arial
ArialMT
Arial-ItalicMT
Arial-BoldMT
Arial-BoldItalicMT
Hiragino Kaku Gothic ProN
HiraKakuProN-W3
HiraKakuProN-W6
AppleGothic
AppleGothic
Heiti SC
STHeitiSC-Light
STHeitiSC-Medium
Malayalam Sangam MN
MalayalamSangamMN-Bold
MalayalamSangamMN
Thonburi
Thonburi
Thonburi-Bold
Helvetica
Helvetica-BoldOblique
Helvetica
Helvetica-Oblique
Helvetica-Bold
Futura
Futura-CondensedExtraBold
Futura-MediumItalic
Futura-Medium
Gujarati Sangam MN
GujaratiSangamMN-Bold
GujaratiSangamMN
Heiti K
STHeitiK-Medium
STHeitiK-Light
Devanagari Sangam MN
DevanagariSangamMN-Bold
DevanagariSangamMN
Heiti TC
STHeitiTC-Light
STHeitiTC-Medium
Sinhala Sangam MN
SinhalaSangamMN
SinhalaSangamMN-Bold
Kannada Sangam MN
KannadaSangamMN-Bold
KannadaSangamMN
Georgia
Georgia-BoldItalic
Georgia-Italic
Georgia-Bold
Georgia
Heiti J
STHeitiJ-Medium
STHeitiJ-Light
Times New Roman
TimesNewRomanPS-BoldMT
TimesNewRomanPS-ItalicMT
TimesNewRomanPS-BoldItalicMT
TimesNewRomanPSMT
Geeza Pro
GeezaPro
GeezaPro-Bold
Helvetica Neue
HelveticaNeue-Bold
HelveticaNeue
Arial Hebrew
ArialHebrew-Bold
ArialHebrew
Zapfino
Zapfino
Oriya Sangam MN
OriyaSangamMN
OriyaSangamMN-Bold
Cochin
Cochin
Cochin-BoldItalic
Cochin-Italic
Cochin-Bold
Baskerville
Baskerville
Baskerville-BoldItalic
Baskerville-Italic
Baskerville-Bold
Verdana
Verdana-Bold
Verdana-BoldItalic
Verdana-Italic
Verdana
Gurmukhi MN
GurmukhiMN
GurmukhiMN-Bold
Palatino
Palatino-BoldItalic
Palatino-Italic
Palatino-Bold
Palatino-Roman
Tamil Sangam MN
TamilSangamMN-Bold
TamilSangamMN
Marker Felt
MarkerFelt-Wide
MarkerFelt-Thin
Courier New
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPS-BoldItalicMT
CourierNewPSMT
Courier
Courier-Oblique
Courier
Courier-Bold
Courier-BoldOblique
DB LCD Temp
DBLCDTempBlack
Trebuchet MS
TrebuchetMS-Italic
Trebuchet-BoldItalic
TrebuchetMS
TrebuchetMS-Bold
Arial Rounded MT Bold
ArialRoundedMTBold
Bangla Sangam MN
BanglaSangamMN
BanglaSangamMN-Bold
Telugu Sangam MN
TeluguSangamMN
TeluguSangamMN-Bold
American Typewriter
AmericanTypewriter-Bold
AmericanTypewriter
Arial
ArialMT
Arial-ItalicMT
Arial-BoldMT
Arial-BoldItalicMT
Hiragino Kaku Gothic ProN
HiraKakuProN-W3
HiraKakuProN-W6
AppleGothic
AppleGothic
Heiti SC
STHeitiSC-Light
STHeitiSC-Medium
Malayalam Sangam MN
MalayalamSangamMN-Bold
MalayalamSangamMN
Thonburi
Thonburi
Thonburi-Bold
Helvetica
Helvetica-BoldOblique
Helvetica
Helvetica-Oblique
Helvetica-Bold
Futura
Futura-CondensedExtraBold
Futura-MediumItalic
Futura-Medium
Gujarati Sangam MN
GujaratiSangamMN-Bold
GujaratiSangamMN
Heiti K
STHeitiK-Medium
STHeitiK-Light
Devanagari Sangam MN
DevanagariSangamMN-Bold
DevanagariSangamMN
Heiti TC
STHeitiTC-Light
STHeitiTC-Medium
Sinhala Sangam MN
SinhalaSangamMN
SinhalaSangamMN-Bold
Kannada Sangam MN
KannadaSangamMN-Bold
KannadaSangamMN
Georgia
Georgia-BoldItalic
Georgia-Italic
Georgia-Bold
Georgia
Heiti J
STHeitiJ-Medium
STHeitiJ-Light
Times New Roman
TimesNewRomanPS-BoldMT
TimesNewRomanPS-ItalicMT
TimesNewRomanPS-BoldItalicMT
TimesNewRomanPSMT
Geeza Pro
GeezaPro
GeezaPro-Bold
Helvetica Neue
HelveticaNeue-Bold
HelveticaNeue
Arial Hebrew
ArialHebrew-Bold
ArialHebrew
Zapfino
Zapfino
Oriya Sangam MN
OriyaSangamMN
OriyaSangamMN-Bold
Cochin
Cochin
Cochin-BoldItalic
Cochin-Italic
Cochin-Bold
Baskerville
Baskerville
Baskerville-BoldItalic
Baskerville-Italic
Baskerville-Bold
Verdana
Verdana-Bold
Verdana-BoldItalic
Verdana-Italic
Verdana
Gurmukhi MN
GurmukhiMN
GurmukhiMN-Bold
Palatino
Palatino-BoldItalic
Palatino-Italic
Palatino-Bold
Palatino-Roman
Tamil Sangam MN
TamilSangamMN-Bold
TamilSangamMN
Marker Felt
MarkerFelt-Wide
MarkerFelt-Thin
Courier New
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPS-BoldItalicMT
CourierNewPSMT
Courier
Courier-Oblique
Courier
Courier-Bold
Courier-BoldOblique
DB LCD Temp
DBLCDTempBlack
Trebuchet MS
TrebuchetMS-Italic
Trebuchet-BoldItalic
TrebuchetMS
TrebuchetMS-Bold
Arial Rounded MT Bold
ArialRoundedMTBold
Bangla Sangam MN
BanglaSangamMN
BanglaSangamMN-Bold
Telugu Sangam MN
TeluguSangamMN
TeluguSangamMN-Bold
American Typewriter
AmericanTypewriter-Bold
AmericanTypewriter
Arial
ArialMT
Arial-ItalicMT
Arial-BoldMT
Arial-BoldItalicMT
Hiragino Kaku Gothic ProN
HiraKakuProN-W3
HiraKakuProN-W6
AppleGothic
AppleGothic
Heiti SC
STHeitiSC-Light
STHeitiSC-Medium
Malayalam Sangam MN
MalayalamSangamMN-Bold
MalayalamSangamMN
Thonburi
Thonburi
Thonburi-Bold
Helvetica
Helvetica-BoldOblique
Helvetica
Helvetica-Oblique
Helvetica-Bold
Futura
Futura-CondensedExtraBold
Futura-MediumItalic
Futura-Medium
Gujarati Sangam MN
GujaratiSangamMN-Bold
GujaratiSangamMN
Heiti K
STHeitiK-Medium
STHeitiK-Light
Devanagari Sangam MN
DevanagariSangamMN-Bold
DevanagariSangamMN
Heiti TC
STHeitiTC-Light
STHeitiTC-Medium
Sinhala Sangam MN
SinhalaSangamMN
SinhalaSangamMN-Bold
Kannada Sangam MN
KannadaSangamMN-Bold
KannadaSangamMN
Georgia
Georgia-BoldItalic
Georgia-Italic
Georgia-Bold
Georgia
Heiti J
STHeitiJ-Medium
STHeitiJ-Light
Times New Roman
TimesNewRomanPS-BoldMT
TimesNewRomanPS-ItalicMT
TimesNewRomanPS-BoldItalicMT
TimesNewRomanPSMT
Geeza Pro
GeezaPro
GeezaPro-Bold
Helvetica Neue
HelveticaNeue-Bold
HelveticaNeue
Arial Hebrew
ArialHebrew-Bold
ArialHebrew
Zapfino
Zapfino
Oriya Sangam MN
OriyaSangamMN
OriyaSangamMN-Bold
Cochin
Cochin
Cochin-BoldItalic
Cochin-Italic
Cochin-Bold
Baskerville
Baskerville
Baskerville-BoldItalic
Baskerville-Italic
Baskerville-Bold
Verdana
Verdana-Bold
Verdana-BoldItalic
Verdana-Italic
Verdana
Gurmukhi MN
GurmukhiMN
GurmukhiMN-Bold
Palatino
Palatino-BoldItalic
Palatino-Italic
Palatino-Bold
Palatino-Roman
Tamil Sangam MN
TamilSangamMN-Bold
TamilSangamMN
Marker Felt
MarkerFelt-Wide
MarkerFelt-Thin
Courier New
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPS-BoldItalicMT
CourierNewPSMT
Courier
Courier-Oblique
Courier
Courier-Bold
Courier-BoldOblique
DB LCD Temp
DBLCDTempBlack
Trebuchet MS
TrebuchetMS-Italic
Trebuchet-BoldItalic
TrebuchetMS
TrebuchetMS-Bold
Arial Rounded MT Bold
ArialRoundedMTBold
Bangla Sangam MN
BanglaSangamMN
BanglaSangamMN-Bold
Telugu Sangam MN
TeluguSangamMN
TeluguSangamMN-Bold
American Typewriter
AmericanTypewriter-Bold
AmericanTypewriter
Arial
ArialMT
Arial-ItalicMT
Arial-BoldMT
Arial-BoldItalicMT
Hiragino Kaku Gothic ProN
HiraKakuProN-W3
HiraKakuProN-W6
AppleGothic
AppleGothic
Heiti SC
STHeitiSC-Light
STHeitiSC-Medium
Malayalam Sangam MN
MalayalamSangamMN-Bold
MalayalamSangamMN
Thonburi
Thonburi
Thonburi-Bold
Helvetica
Helvetica-BoldOblique
Helvetica
Helvetica-Oblique
Helvetica-Bold
Futura
Futura-CondensedExtraBold
Futura-MediumItalic
Futura-Medium
Gujarati Sangam MN
GujaratiSangamMN-Bold
GujaratiSangamMN
Heiti K
STHeitiK-Medium
STHeitiK-Light
Devanagari Sangam MN
DevanagariSangamMN-Bold
DevanagariSangamMN
Heiti TC
STHeitiTC-Light
STHeitiTC-Medium
Sinhala Sangam MN
SinhalaSangamMN
SinhalaSangamMN-Bold
Kannada Sangam MN
KannadaSangamMN-Bold
KannadaSangamMN
Georgia
Georgia-BoldItalic
Georgia-Italic
Georgia-Bold
Georgia
Heiti J
STHeitiJ-Medium
STHeitiJ-Light
Times New Roman
TimesNewRomanPS-BoldMT
TimesNewRomanPS-ItalicMT
TimesNewRomanPS-BoldItalicMT
TimesNewRomanPSMT
Geeza Pro
GeezaPro
GeezaPro-Bold
Helvetica Neue
HelveticaNeue-Bold
HelveticaNeue
Arial Hebrew
ArialHebrew-Bold
ArialHebrew
Zapfino
Zapfino
Oriya Sangam MN
OriyaSangamMN
OriyaSangamMN-Bold
Cochin
Cochin
Cochin-BoldItalic
Cochin-Italic
Cochin-Bold
Baskerville
Baskerville
Baskerville-BoldItalic
Baskerville-Italic
Baskerville-Bold
Verdana
Verdana-Bold
Verdana-BoldItalic
Verdana-Italic
Verdana
Gurmukhi MN
GurmukhiMN
GurmukhiMN-Bold
Palatino
Palatino-BoldItalic
Palatino-Italic
Palatino-Bold
Palatino-Roman
Tamil Sangam MN
TamilSangamMN-Bold
TamilSangamMN
Marker Felt
MarkerFelt-Wide
MarkerFelt-Thin
Courier New
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPS-BoldItalicMT
CourierNewPSMT
Courier
Courier-Oblique
Courier
Courier-Bold
Courier-BoldOblique
DB LCD Temp
DBLCDTempBlack
Trebuchet MS
TrebuchetMS-Italic
Trebuchet-BoldItalic
TrebuchetMS
TrebuchetMS-Bold
Arial Rounded MT Bold
ArialRoundedMTBold
Bangla Sangam MN
BanglaSangamMN
BanglaSangamMN-Bold
Telugu Sangam MN
TeluguSangamMN
TeluguSangamMN-Bold
American Typewriter
AmericanTypewriter-Bold
AmericanTypewriter
Arial
ArialMT
Arial-ItalicMT
Arial-BoldMT
Arial-BoldItalicMT
Hiragino Kaku Gothic ProN
HiraKakuProN-W3
HiraKakuProN-W6
AppleGothic
AppleGothic
Heiti SC
STHeitiSC-Light
STHeitiSC-Medium
Malayalam Sangam MN
MalayalamSangamMN-Bold
MalayalamSangamMN
Thonburi
Thonburi
Thonburi-Bold
Helvetica
Helvetica-BoldOblique
Helvetica
Helvetica-Oblique
Helvetica-Bold
Futura
Futura-CondensedExtraBold
Futura-MediumItalic
Futura-Medium
Gujarati Sangam MN
GujaratiSangamMN-Bold
GujaratiSangamMN
Heiti K
STHeitiK-Medium
STHeitiK-Light
Devanagari Sangam MN
DevanagariSangamMN-Bold
DevanagariSangamMN
Heiti TC
STHeitiTC-Light
STHeitiTC-Medium
Sinhala Sangam MN
SinhalaSangamMN
SinhalaSangamMN-Bold
Kannada Sangam MN
KannadaSangamMN-Bold
KannadaSangamMN
Georgia
Georgia-BoldItalic
Georgia-Italic
Georgia-Bold
Georgia
Heiti J
STHeitiJ-Medium
STHeitiJ-Light
Times New Roman
TimesNewRomanPS-BoldMT
TimesNewRomanPS-ItalicMT
TimesNewRomanPS-BoldItalicMT
TimesNewRomanPSMT
Geeza Pro
GeezaPro
GeezaPro-Bold
Helvetica Neue
HelveticaNeue-Bold
HelveticaNeue
Arial Hebrew
ArialHebrew-Bold
ArialHebrew
Zapfino
Zapfino
Oriya Sangam MN
OriyaSangamMN
OriyaSangamMN-Bold
Cochin
Cochin
Cochin-BoldItalic
Cochin-Italic
Cochin-Bold
Baskerville
Baskerville
Baskerville-BoldItalic
Baskerville-Italic
Baskerville-Bold
Verdana
Verdana-Bold
Verdana-BoldItalic
Verdana-Italic
Verdana
Gurmukhi MN
GurmukhiMN
GurmukhiMN-Bold
Palatino
Palatino-BoldItalic
Palatino-Italic
Palatino-Bold
Palatino-Roman
Tamil Sangam MN
TamilSangamMN-Bold
TamilSangamMN
Marker Felt
MarkerFelt-Wide
MarkerFelt-Thin
Courier New
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPS-BoldItalicMT
CourierNewPSMT
Courier
Courier-Oblique
Courier
Courier-Bold
Courier-BoldOblique
DB LCD Temp
DBLCDTempBlack
Trebuchet MS
TrebuchetMS-Italic
Trebuchet-BoldItalic
TrebuchetMS
TrebuchetMS-Bold
Arial Rounded MT Bold
ArialRoundedMTBold
Bangla Sangam MN
BanglaSangamMN
BanglaSangamMN-Bold
Telugu Sangam MN
TeluguSangamMN
TeluguSangamMN-Bold
American Typewriter
AmericanTypewriter-Bold
AmericanTypewriter
Arial
ArialMT
Arial-ItalicMT
Arial-BoldMT
Arial-BoldItalicMT
Hiragino Kaku Gothic ProN
HiraKakuProN-W3
HiraKakuProN-W6
AppleGothic
AppleGothic
Heiti SC
STHeitiSC-Light
STHeitiSC-Medium
Malayalam Sangam MN
MalayalamSangamMN-Bold
MalayalamSangamMN
Thonburi
Thonburi
Thonburi-Bold
Helvetica
Helvetica-BoldOblique
Helvetica
Helvetica-Oblique
Helvetica-Bold
Futura
Futura-CondensedExtraBold
Futura-MediumItalic
Futura-Medium
Gujarati Sangam MN
GujaratiSangamMN-Bold
GujaratiSangamMN
Heiti K
STHeitiK-Medium
STHeitiK-Light
Devanagari Sangam MN
DevanagariSangamMN-Bold
DevanagariSangamMN
Heiti TC
STHeitiTC-Light
STHeitiTC-Medium
Sinhala Sangam MN
SinhalaSangamMN
SinhalaSangamMN-Bold
Kannada Sangam MN
KannadaSangamMN-Bold
KannadaSangamMN
Georgia
Georgia-BoldItalic
Georgia-Italic
Georgia-Bold
Georgia
Heiti J
STHeitiJ-Medium
STHeitiJ-Light
Times New Roman
TimesNewRomanPS-BoldMT
TimesNewRomanPS-ItalicMT
TimesNewRomanPS-BoldItalicMT
TimesNewRomanPSMT
Geeza Pro
GeezaPro
GeezaPro-Bold
Helvetica Neue
HelveticaNeue-Bold
HelveticaNeue
Arial Hebrew
ArialHebrew-Bold
ArialHebrew
Zapfino
Zapfino
Oriya Sangam MN
OriyaSangamMN
OriyaSangamMN-Bold
Cochin
Cochin
Cochin-BoldItalic
Cochin-Italic
Cochin-Bold
Baskerville
Baskerville
Baskerville-BoldItalic
Baskerville-Italic
Baskerville-Bold
Verdana
Verdana-Bold
Verdana-BoldItalic
Verdana-Italic
Verdana
Gurmukhi MN
GurmukhiMN
GurmukhiMN-Bold
Palatino
Palatino-BoldItalic
Palatino-Italic
Palatino-Bold
Palatino-Roman
Tamil Sangam MN
TamilSangamMN-Bold
TamilSangamMN
Marker Felt
MarkerFelt-Wide
MarkerFelt-Thin
Courier New
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPS-BoldItalicMT
CourierNewPSMT
Courier
Courier-Oblique
Courier
Courier-Bold
Courier-BoldOblique
DB LCD Temp
DBLCDTempBlack
Trebuchet MS
TrebuchetMS-Italic
Trebuchet-BoldItalic
TrebuchetMS
TrebuchetMS-Bold
Arial Rounded MT Bold
ArialRoundedMTBold
Bangla Sangam MN
BanglaSangamMN
BanglaSangamMN-Bold
Telugu Sangam MN
TeluguSangamMN
TeluguSangamMN-Bold
American Typewriter
AmericanTypewriter-Bold
AmericanTypewriter
Arial
ArialMT
Arial-ItalicMT
Arial-BoldMT
Arial-BoldItalicMT
Hiragino Kaku Gothic ProN
HiraKakuProN-W3
HiraKakuProN-W6
AppleGothic
AppleGothic
Heiti SC
STHeitiSC-Light
STHeitiSC-Medium
Malayalam Sangam MN
MalayalamSangamMN-Bold
MalayalamSangamMN
Thonburi
Thonburi
Thonburi-Bold
Helvetica
Helvetica-BoldOblique
Helvetica
Helvetica-Oblique
Helvetica-Bold
Futura
Futura-CondensedExtraBold
Futura-MediumItalic
Futura-Medium
Gujarati Sangam MN
GujaratiSangamMN-Bold
GujaratiSangamMN
Heiti K
STHeitiK-Medium
STHeitiK-Light
Devanagari Sangam MN
DevanagariSangamMN-Bold
DevanagariSangamMN
Heiti TC
STHeitiTC-Light
STHeitiTC-Medium
Sinhala Sangam MN
SinhalaSangamMN
SinhalaSangamMN-Bold
Kannada Sangam MN
KannadaSangamMN-Bold
KannadaSangamMN
Georgia
Georgia-BoldItalic
Georgia-Italic
Georgia-Bold
Georgia
Heiti J
STHeitiJ-Medium
STHeitiJ-Light
Times New Roman
TimesNewRomanPS-BoldMT
TimesNewRomanPS-ItalicMT
TimesNewRomanPS-BoldItalicMT
TimesNewRomanPSMT
Geeza Pro
GeezaPro
GeezaPro-Bold
Helvetica Neue
HelveticaNeue-Bold
HelveticaNeue

Wednesday, August 11, 2010

Blender 2.5 Objective-C Export Script

Paul Horalek has taken my old Blender 2.49 script for exporting 3D objects to Objective-C header files and has ported it to the new Blender 2.5 Python API. I'd been meaning to do this for quite some time, as I've been using Blender 2.5 since the early alpha releases, but never found time. Now I don't have to.

You can find the new version of the script right here.

Thanks, Paul!

NSOperation File Template Notes

I've had a few questions about the NSOperation subclass file template I posted earlier. Instead of individually responding, I thought I'd clarify here:

First, in order to use the templates, you'll need a couple of categories on NSInvocation that you can find here. I forgot that those methods weren't part of NSInvocation because I use them so frequently.

Also, you'll notice replacement tokens in the template, similar to those you get for parameters when you use autocomplete with a method or function. This was intentional. If I had used any of the file template replacement tokens, the delegate methods would have begun with a capital letter and the method names wouldn't have always made sense. Instead, you have to replace the tokens with a value - the same value.

In theory, typing the value for one replacement token should change the value for all replacement tokens of the same name, but it doesn't seem to work in the header file, for some reason I haven't been able to figure out yet.

Anyway, hope that helps with some of the confusion.

Tuesday, August 10, 2010

Call for Testers!

Update: All of my available device slots are gone.

Okay, I've got room in my device list for 15 testers for the Library of Congress Prints and Photographs application. I'd love to accept more, but the 100 device limit prevents me from using too many slots for a personal side project like this.

There's a catch: I need at least one device running iOS 3.1.x and at least one older device (3G, Original iPhone, 1st or 2nd gen iPod touch). Ideally, I'd have a nice spread of devices. The iPad won't be supported in the first release, so iPhone and iPod touch users only please. I'm considering adding iPad at a future date, but don't have the time to devote to it at the moment.

I expect to distribute the first beta build by the end of the week, possibly earlier, but no promises, since client work and the book have to take priority. I have one bug I still need to chase down and one feature I still want to add, and then I'll be ready to distribute.

If interested, e-mail me with what model device you have and the iOS version you're running. If I can use you, I'll respond and have you can send me your UDID. This will mostly be first-come-first-served, except I may have to skip people to make sure I get at least one older device and one older version of iOS.

P.S. My e-mail address is my twitter name at mac dot com.

Thursday, August 5, 2010

Testers, Maybe?

I read on Daring Fireball yesterday about the new Library of Congress iPhone application. I love libraries, museums, and any large collection of interesting data and was really excited about this app.

It's a nice app, and a really good start for the Library of Congress, but it's missing something I wanted: access to the Prints & Photographs Online Collection. For over a decade, the Library of Congress has been digitizing material from their collections and putting them online. Unfortunately, the web interface is kinda weak on a computer and nigh unusable on an iPhone. Which is too bad, because there's a lot of really cool stuff in here, including works by and photographs of many famous artists such as Ansel Adams, Alice Boughton, Edward Weston, Pablo Picasso, Henri Matisse and many others. There is also a huge amount of historical photographs, artworks, and documents going back to the founding of our country and even earlier. It's the kind of place you can easily lose hours exploring.

I actually hacked out an iPhone app for searching the Prints & Photographs Collections quite a while back. I started it originally because I wanted to play with a few things I hadn't used yet, like iAds, and I find it's easier to do so if I'm writing a "real" app rather than just playing.

And when I say "hacked out", I'm not exaggerating in this case. This wasn't architected so much as thrown together. It started out an entry page where you enter a search term, and then a single table view with the results. I wrote it in one Saturday night after several beers, scope creep increasing with each new beer. But… it works and seems to work pretty well. I spent another couple of hours this evening cleaning up the rough edges and running it through Instruments. I've got a short list of bugs I need to fix, but it probably needs not more than a day's worth of work before it could go to testers.

After the Library of Congress came out with their own app and it didn't include this functionality, I started thinking it might be worth throwing this on the app store as a free app to complement the official one. The ads might generate a little income, but I don't expect very much from what I've heard about iAds fill-rate, and it doesn't really matter, most of the work is already done. Be kinda nice if one of the many abandoned apps in my dev folder got to see the light of day.

So, what do you think? Any interest? I've attached some screenshots of the app so you can see how it works. You can click them for full iPhone 4 resolution. Let me know in the comments if you think this is an app you'd download and also let me know if you're interested in testing.

photo 2.PNG

photo 1.PNG

photo 3.PNG

photo 4.PNG

photo 5.PNG

photo.PNG

Xcode 3, Instruments 4

This was a bit of a "duh" moment for me, but probably worth mentioning, despite being a "Captain Obvious" post.

I'm a big fan of what Apple's doing with Xcode 4, but in my opinion it's just not ready for production use yet. I'm using it for the book and occasional forays, but not for regular client work yet. However, I also run my machine using the 64-bit kernel, which means I can't use Shark without rebooting. I've been really looking forward to the Time Profiler template in the 4.0 version of Instruments as well as the two new OpenGL ES templates and the Energy Diagnostics template.

But, while grumbling about their lack in the current release version of Instruments, it struck me: you don't have to launch Instruments from the same folder you launch Xcode from. You can launch Instruments separately and attach it to a running process in the Simulator or on an attached iPhone. That means, you can launch Instruments from the Xcode4 folder instead of from the Developer folder. This allows you to develop and debug with the less-shiny-but-production-ready Xcode 3.x and also use the new Instruments templates like Time Profiler, OpenGL ES, and Energy Diagnostics.

Monday, August 2, 2010

Core Data Odds and Ends

I've been doing a fair bit of work with Core Data lately, and have picked up a few tricks to make my life easier, so I thought I'd share.

Mo' Power


Back in the EOF days, there was a great little piece of third-party software called EOGenerator that implemented something called the generation gap design pattern. Essentially, this little program would create your custom subclasses of EOGenericRecord (EOF's equivalent of NSManagedObject) for you. It wouldn't just create that, though, it would actually create two classes for each entity in your EOModel.

One of these two classes was yours to modify as you saw fit. It would never get overwritten even if you ran the EOGenerator script again, over and over. The other class contained all the generated code derived from your EOModel and was designed not to be touched by the programmer. You had your class, EOGenerator had its class, and you could both work without any fear of stepping on each other's toes. You could add attributes and entities to your data model and regenerate the machine-readable classes without any chance of losing your custom validation or methods. It was nice.

Wolf Rentzsch has re-implemented this idea for Core Data, and the result is called MOGenerator. If you spend any time with Core Data and aren't familiar with MOGenerator, go become familiar with it. It will make your life much, much, much better.

SQLite to Check Data


The default persistent store type for Core Data under iOS is a SQLite store, which means that Core Data keeps all of its data inside of a single SQLite database in your application's /Documents folder. Now, the format of the persistent store is undocumented and you should never, ever, ever, ever, never change data in the persistent store or make any assumptions about how Core Data stores the data. That's part of why we use Core Data: It's an abstraction layer that lets us not worry about the underlying storage details.

But, sometimes, it can be really helpful to know whether data is getting into the persistent store or not. I often work on my data model before my user interface, so being able to peek in the data store to make sure all is well is really helpful.

The first thing you might want to consider doing, if you plan to do that, is to create a SQLite config file. This is a file of commands that will execute whenever you launch SQLite. To do that, simply create a file called .sqliterc in your home directory. Here's what mine looks like:
.mode column
.header on
.table
In mine, the first line tells SQLite to print the column names when I issue a SELECT command. The second line tells SQLite to present the data in tabular form. The last line prints out a list of all the tables in the database before it shows me the SQL command prompt. That's handy given that the table names don't usually exactly match your entity or class names.

Once you have a config file in place, you can open up any persistent store using the sqlite3 command in Terminal.app, like so:
sqlite3 MyApplication.sqlite
You can't, of course, execute this directly against database files on your phone, but you can do it in the simulator as well as on files copied from your phone using Xcode's Organizer. If you're using the simulator, you can look for your SQLite databases at the following location:
/Users/[your account name]/Library/Application Support/iPhone Simulator/[SDK version #]/Applications/[application UUID]/Documents/[Application Name].sqlite


When I log into a database with my SQLite config file, this is what I see:
-- Loading resources from /Users/jeff/.sqliterc
ZHERO ZPOWER Z_METADATA Z_PRIMARYKEY
SQLite version 3.6.12
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>
Notice that it has dumped the names of all my tables. It's pretty easy to figure out which table holds what data once they're right in front of you. The example above is the persistent store from the SuperDB application from More iPhone 3 Development. The Hero entity managed objects are stored in ZHERO and the Power entity managed objects are stored in ZPOWER. To look at the contents of a table, you just need to execute a SQL SELECT command. The simplest is just SELECT * FROM TABLENAME;, which prints the entire contents of the table to the console, like so:
sqlite> select * from ZPOWER;
Z_PK Z_ENT Z_OPT ZHERO ZSOURCE ZNAME
---------- ---------- ---------- ---------- ---------- ----------
1 2 2 1 Mutation Fire
sqlite>
The format of the data is pretty easy to figure out but, again, you really should look and not touch. It'd be very easy to accidentally destroy a persistent store. A seemingly inconsequential change could get the metadata out of whack and prevent your app from using the persistent store any more.

Better Descrption


I noticed a few days ago that Wil Shipley was complaining about the fact that many of Apple's delivered UIKit and Foundation objects have not overridden the -description method. This method is important because it's the one that is used in format strings, NSLog(), and when you type the po command in GDB. Instead of getting a meaningful description of many delivered objects, you instead get the class name and memory address of the instance, which is what NSObject's implementation provides, which isn't very much help while debugging.

Unfortunately, NSManagedObject is one of the many, many classes that doesn't have its own meaningful implementation of -description. That doesn't mean you can't provide one, though.

One thing you can do is to create an abstract subclass of NSManagedObject and put the -description method there. If you then subclass this abstract class, all of your managed objects will inherit the method from the abstract class. If I have other common functionality, I'll often do exactly that. But if I don't (and often you won't) I personally hate to clutter up my object hierarchy to add debugging tools. So I actually will cheat and do something you're not really supposed to do, which is override a method using a category. The reason it's bad to do this is because the Objective-C language does not specify which method should be used, which can lead to unpredictable behavior. But, when a class inherits a method from a superclass, I've found that overriding it in a category always works. I'm not suggesting you should do this in a shipping app, however. I wrap my method in pre-compiler definitions so that it doesn't get compiled into the release version of my application.

My version of -description assumes you're generating properties for your managed objects (I always do) and also assumes you're using custom subclasses (but you are, because you're using MOGenerator, right??). The method iterates over all the properties of the class and all its superclasses up to NSManagedObject, then prints them to the console. The categories I use look like this:
#if DEBUG
@implementation NSObject(MCManagedObjectDebug)
+ (NSMutableArray *)MCproperties
{
NSMutableArray *properties = nil;

if ([self superclass] != [NSManagedObject class])
properties = [[self superclass] MCproperties];
else
properties = [NSMutableArray array];


unsigned int propCount;
objc_property_t * propList = class_copyPropertyList([self class], &propCount);
int i;

for (i=0; i < propCount; i++)
{
objc_property_t oneProp = propList[i];
NSString *propName = [NSString stringWithUTF8String:property_getName(oneProp)];
if (![properties containsObject:propName])
[properties addObject:propName];
}

return properties;
}

@end


@implementation NSManagedObject(MCManagedObjectDebug)
- (NSString *)description
{
NSArray *properties = [[self class] MCproperties];
NSMutableString *ret = [NSMutableString stringWithFormat:@"%@:", [self className]];
NSDictionary *myAttributes = [[self entity] attributesByName];

for (NSString *oneProperty in properties)
{
NSAttributeDescription *oneAttribute = [myAttributes valueForKey:oneProperty];
if (oneAttribute != nil) // If not, it's a relationship or fetched property
{
id value = [self valueForKey:oneProperty];
[ret appendFormat:@"\n\t%@ = %@", oneProperty, value];
}


}

return ret;
}


@end
#endif
The +MCProperties method uses the Objective-C runtime to discover and iterate over properties in the class definition, including @dynamic properties that were created at runtime. Because the property runtime calls do not include properties inherited from parent classes, the method acts recursively, iterating up the object hierarchy until it gets to NSManagedObject. The actual -description method simply prints out each of the attributes and the value currently stored for that attribute for this object instance. Once you do this, if you use NSLog() or po, the result is much richer information about the objects getting printed to the console. This version ignores relationships and fetched properties, but it wouldn't be hard to add those in if you needed them.

Time Moves On…

Justin from CarpeAqua has an interesting rant this morning about pull-to-refresh. I don't expect everybody to like every new mode of interaction that gets introduced (I certainly don't), and I've been known to rant myself at times, but I must admit I don't quite get the fervor with which some people, like Justin, hate experimentation with new methods of interaction.

In his post, Justin sums up his feelings by quoting a tweet by Marco Arment that reads:
The problem, like gradients, reflections, animations, and PHP, is not that it's a bad idea but that many won't use it properly.
This argument reminds me of the arguments I've heard against dot notation in Objective-C. It amounts to "somebody might use it poorly, therefore it's bad".

I've got news for you: There's almost nothing in life you can't say that about. If you're holding up the potential abuse of something as a reason not to use it, then you're making excuses for your own desire for things to stay as they always were. In the history of human innovation, there's almost nothing that couldn't be abused or put to an inappropriate use.

Sure, you can do this with Objective-C 2.0+:
someObject.release;
That's a perfectly legal way to release an object. Most, including me, would argue that it's not a good way; it's likely to cause confusion and makes the intention of your code harder to read. But, just because you can do this doesn't mean dot notation is inherently flawed (though a vocal minority of Objective-C developers argue exactly that). The same thing goes for gradients, reflections, PHP, animations and, yes, pull-to-refresh. Actually, scratch that… PHP really is bad¹. But the rest of them aren't.

Even the greatest interaction ideas can be mis-used and over-used and, in fact, they usually are. I'd almost argue that they have to be. All ideas get refined as they are used more. It's natural behavior to explore, expand, and find the limits of any new idea. Thought experiments are all well and good, but until you get a new mode of interaction in front of a lot of people to try it, all you've got is your best guess based on your own opinion. In other words, overuse of the novel isn't, in the scheme of things, a bad thing. Over time, the overuse ends and we're left with something we understand much, much better and that works really, really well.

Basically, we don't know how to use new concepts "properly" until they've been used a lot, in a lot of different ways, by a lot of different people. There's nothing to guide the use of the novel. There's no way to find what works and what doesn't except by trying. And sometimes the things we try won't work, or won't work for all people. Sometimes they'll be downright bad.

A lot of our current desktop interaction model, things that we think of as universal and standard, weren't always standard or universal. I can remember when ⌘C, ⌘X, ⌘V, and ⌘P did not automatically mean cut, copy, paste, and print on the Mac. It took several years for key commands to truly become standard and universal on the Mac. Heck, many early versions of Mac applications didn't make much use of key shortcuts at all, and when they did, they weren't at all consistent in which keys they used to do what. You can't dictate what works in user interaction. You have to put it out there, observe and listen, and be willing to change based on what you see and hear.

Personally, I like pull-to-refresh as it's used in Tweetie Twitter. I find myself doing it in Mail.app, even though it doesn't work there. To me, it's the perfect gesture for the iPhone in apps where you're primarily consuming small chunks of content in a table, like your inbox or twitter apps. When I'm using apps of this nature, I'm often in one-handed mode, using my thumb to scroll. My thumb can't comfortably reach the entire screen (e.g. a refresh button in the navigation bar), and I don't want to bring my other hand over every time I want new tweets. When I'm in editing mode, I'm naturally using my other hand, and that's great, but if I'm standing in line at the grocery store or waiting to board a plane and I'm just reading my timeline, I like that I can just flick my thumb to get more tweets. It's a benefit to me to be able to work one handed. It's a nearly ideal form of interaction for the way I use the application most of the time. Obviously, I'm not the only one who feels this way. You don't see lots of people rushing to copy features that don't work or aren't liked.

In other apps, or especially on the iPad, pull-to-refresh doesn't seem like it would be a natural form of interaction, but I've never tried pull-to-refresh in other contexts, so I don't know. But developers will try it (and are trying it), and many uses of pull-to-refresh that don't work well will die. Either the application will fail to sell, or the author will decide to change it to something that works better for his or her users. But we might just discover new and wonderful uses for the concept in the process.

That's how this whole messy process works. That's how we get progress in user interaction. We try things. Sometimes they work, often they don't. If, as developers, we only use things that are tried and true, nothing will ever change.

Progress in user interaction, like anything else where hard-to-predict humans play a major role, is messy and slow and imperfect and no amount of ranting about it will change that fact. If we want progress... if we want to keep moving forward, that's the price we pay. You can get angry about it, but you can't change it. You'd have about as much luck arguing with the weather.



1 No, not really. That was a joke.

Sunday, August 1, 2010

NSOperation Xcode File Template

Although I'm generally averse to using a lot of template or boilerplate code, there are times when it's handy to have file template beyond those that Apple provides. Something I've done a fair amount of lately is to create NSOperation subclasses, and there's enough work involved with setting up an operation that I made an Xcode file template that contains all that setup work.

This template includes a delegate and a protocol and some private methods for communicating with the delegate. Now, when I have lots of NSOperation subclasses in a single project, I'll actually move much of this stuff to an abstract parent class or a category on NSOperation, but templates don't have any way of setting up dependencies, so I've made this self-contained and you can do your own refactoring.

I added this particular template under the Objective-C class icon so that it comes up as a new option under the Subclass of popup menu.

Screen shot 2010-08-01 at 1.53.48 PM.png

You can find the template files right here. The zip file contains the full path to install everything in the correct place, so if you want to install it so that you can use it from Xcode, you would use the following command:
unzip NSOperationTemplate.zip -d /

If you just unzip it regularly, you'll find the actual files nested several folders down as a result of the path information.

I've only touched one existing file, which is a property list that causes the new template to show up in Xcode's Subclass of dropdown menu. The rest are new files, so installing this shouldn't interfere with Xcode in any way. But caveat emptor. You do keep good backups, right?

Hopefully this will be useful to some of you. If you have suggestions for making it better, please let me know.

 
Design by Wordpress Theme | Bloggerized by Free Blogger Templates | coupon codes