In Objective-C, alloc/release really annoy.

NSString* string = [[NSString alloc] initWithFormat:@"hello %@", world];
...
[string release];
NSMutableArray* array = [[NSMutableArray alloc] init];
...
[array release];

Use autorelease can make code simple and clear

NSString* string = [[NSString alloc] stringWithFormat:@"hello %@", world];
...
NSMutableArray* array = [NSMutableArray array];
...

but when will the autoreleased object will be really released? I google it and got the answer is that Cocoa will create the invisible autorelease pools and release them for every event handling in event loop.

So maybe the best practice is use the autorelease as possible as we can, then try to find the memory leak when performance tuning. And use alloc/release or create own autorelease pool to optimize the memory usage.

 

The custom font support is one of the new features since iOS 3.2, see here for how to do it. After you added your own font, you can just create UIFont as following:

UIFont* myFont = [UIFont fontWithName:@"myOwnFontName" size:fontSize];

Then you can use myFont anywhere. However, there have issues when using Core Text. As we know, to specify the text styles, font or color, for rendering text with Core Text, we need create a NSAttributedString, then config the attributes. Core Text only accept CTFontRef instead of UIFont, but following code cause my application hang:

CTFontRef font = CTFontCreateWithName(CFSTR("myOwnFontName"), fontSize,NULL);

After some investigation, I finally got following working code:

UIFont* myFont = [UIFont fontWithName:@"myOwnFontName" size:fontSize];
CTFontRef font = CTFontCreateWithName(CFSTR("myOwnFontName"), fontSize,NULL);
NSMutableAttributedStringRef attrString = [[NSMutableAttributedString alloc] initWithString:someString];
[attrString addAttribute:(NSString*)kCTFontAttributeName
               value:(id)font
               range: NSMakeRange(0, someString.length)];

Seems UIFont did some staff for custom font, but CTFontCreateWithName didn't.

Recently I am creating a simple demo to demonstrate text layout features on the iPad. These features include text columns, text hyphenation and text fully justification. I finally chose to use Core Text to do this, because I didn't find a way to do text fully justification just by using UITextView or UIWebView.

The Core Text is a new framework available on iOS 3.2, give a lot of good features for text layout. It's easy to split text into several columns, and fully justified. But text hyphenation isn't a built-in feature. I google it and found a very useful article. From the article, I know how and where to insert soft hyphen into a string. The UITextView and UIWebView can render the string correctly, break lines as hyphenation suggests, and especially they'll add the hyphen mark "-" at the end of the line. But Core Text won't.

I spent some time to study how to add such a hyphen mark to the end of line with CoreText. And finally got a solution as following:

  1. Break CTFrame into CTLines by CTFrameGetLines(frame)
  2. Check every CTLine object, check if the last character is soft hyphen(0x00AD)
  3. Create a new CTLine with last character replaced by "-"
  4. Draw CTLines instead of draw CTFrames.

See screenshot:

hyphenation

Following are some code for how to find the line with soft hyphen and replace it with "-":

//handle text hyphenation
CFRange cfStringRange = CTLineGetStringRange(line);
NSRange stringRange = NSMakeRange(cfStringRange.location, cfStringRange.length);
static const unichar softHypen = 0x00AD;
unichar lastChar = [textString characterAtIndex:stringRange.location + stringRange.length-1];

if(softHypen == lastChar) {
	NSMutableAttributedString* lineAttrString = [[_attrString attributedSubstringFromRange:stringRange] mutableCopy];
	NSRange replaceRange = NSMakeRange(stringRange.length-1, 1);
	[lineAttrString replaceCharactersInRange:replaceRange withString:@"-"];

	CTLineRef hyphenLine = CTLineCreateWithAttributedString((CFAttributedStringRef)lineAttrString);
        CTLineRef justifiedLine = CTLineCreateJustifiedLine(hyphenLine, 1.0, lineWidth); 

	CTLineDraw(justfiedLine);
} else {
        CTLineDraw(originalLine);
}