Text

Running Unit Tests from the CLI via Xcode 4

First make your test target depend on the actual app, then do this:

$ xcodebuild build -target $TARGET_NAME -configuration $BUILD_CONFIGURATION -sdk iphonesimulator SYMROOT="$TEMP_DIR"

It’ll then build and run like a normal build operation. I have not yet looked into any way to configure Test Document Data / Test Location via the CLI without resorting to scripting yet.

Text

Conditional Objective-C blocks

This trick allows use of conditional blocks thru the C preprocessor:

//  Mix and match

#if USES_TESTFLIGHT
    #import "TestFlight.h"
    #define TESTFLIGHT(...) do { (__VA_ARGS__)(); } while (0)   
#else
    #define TestFlight (id)nil
    #define TESTFLIGHT(...) do {  } while (0)   
#endif
Link

A tiny shell script that builds stuff thru `xcodebuild` because Jenkins configuration is hard enough.

Video

Tech Startups?

Text

Super Poking

This lets you know if it’s safe to call super:

+ (BOOL) superMethodDiffers:(SEL)aSelector {

    Method ownMethod = class_getClassMethod([self class], aSelector);
    Method superMethod = class_getClassMethod([self superclass], aSelector);

    return (superMethod && (superMethod != ownMethod));

}

- (BOOL) superMethodDiffers:(SEL)aSelector {

    Method ownMethod = class_getInstanceMethod([self class], aSelector);
    Method superMethod = class_getInstanceMethod([self superclass], aSelector);

    return (superMethod && (superMethod != ownMethod));

}
Text

-waitUntilAllOperationsAreFinished

The Problem

Unbounded problems aren’t easy to resolve because most SDKs and toolkits are designed to resolve one-off problems, for example:

List the contents of this directory, then when you’re done give me a call.

If you’re dealing with local resources, you’ll almost always use a synchronous method that smells pretty procedural (like NSFileManager). No trouble to be had there. :)

If the resource is laggy, far away, or otherwise generally not ideal for synchronous access, it’s almost granted that you’ll spin up an object, set its delegate to your object (that lives longer), then call some method (which returns void), and wait for the object to call some method (thru delegation) on your object (like NSURLConnection).

This, then, is more challenging:

Recursively list the contents of this directory, and when you’re all done, give me a call.

The approach used to resolve the first problem is going to leave a mess, because for every subdirectory there’s going to be one more delegate call, and there’s usually no way to know if the last invocation was the last one.

If another bunch of stuff needs to be done only after the unbounded operation has finished, then things are going to be even messier. But a private NSOperationQueue makes it easily managable.

Interim Solution

My first attempt at this problem uses a private NSOperationQueue:

  • Create a NSOperationQueue, then set its max number of concurrent operations to 1.
  • Create a generator that can be called multiple times, with each invocation scheduling a new concurrent NSOperation on the queue.
  • Make sure the scheduled operation calls its generator to schedule more work before the operation finishes.
  • Suspend the queue, then call -waitUntilAllOperationsAreFinished and resume the queue.

If you prefer not blocking up the main thread, try doing the magic on another operation queue. For example, schedule an NSBlockOperation that only waits for the private queue to be emptied, and cleans it up thereafter. ;)

Text

Drawing single-line-height text without abandoning CTFramesetterRef and CTFrameRef

Core Text is lightweight and all awesome. But we have this pesky little problem with multilingual layouts — different fonts are created by different vendors and typographers, and they often mismatch in terms of metrics. Some are taller, some shorter; some have huge ascender and descenders, some relatively tiny and tame. Things are quite manageable with just one language, but it’s not the case for me.

We need layouts with even baselines, which runs orthogonal to how the CTFramesetter works. The frame setter calculates typographic bounds, adds up ascender, descender and leading, then use the whole sum as the height of the line. This is straightforward as in it works like movable type, but also painful as it can wreak havoc with baseline alignment.

No, you don’t have to roll your own CTFramesetter implementation. That’s too much pain. Re-implementing something when you can hack and use all the free stuff? No way, that’ll take a whole week.

Creating a well-hacked attributed string

To ensure that your Core Text label draws even line heights, make sure the attributed string you feed into your label is well-hacked:

- (NSAttributedString *) attributedStringForString:(NSString *)aString font:(UIFont *)aFont color:(UIColor *)aColor {

    if (!aString)
        return nil;

    float_t lineHeight = aFont.leading;

    id fontAttr = [NSMakeCollectable(CTFontCreateWithName((CFStringRef)aFont.fontName, aFont.pointSize, NULL)) autorelease];
    id foregroundColorAttr = (id)(aColor ? aColor.CGColor : [UIColor blackColor].CGColor);
    id paragraphStyleAttr = ((^ {

        CTParagraphStyleSetting paragraphStyles[] = (CTParagraphStyleSetting[]){
            (CTParagraphStyleSetting){ kCTParagraphStyleSpecifierLineHeightMultiple, sizeof(float_t), (float_t[]){ 0.01f } },
            (CTParagraphStyleSetting){ kCTParagraphStyleSpecifierMinimumLineHeight, sizeof(float_t), (float_t[]){ lineHeight } },
            (CTParagraphStyleSetting){ kCTParagraphStyleSpecifierMaximumLineHeight, sizeof(float_t), (float_t[]){ lineHeight } },
            (CTParagraphStyleSetting){ kCTParagraphStyleSpecifierLineSpacing, sizeof(float_t), (float_t[]){ 0.0f } },
            (CTParagraphStyleSetting){ kCTParagraphStyleSpecifierMinimumLineSpacing, sizeof(float_t), (float_t[]){ 0.0f } },
            (CTParagraphStyleSetting){ kCTParagraphStyleSpecifierMaximumLineSpacing, sizeof(float_t), (float_t[]){ 0.0f } }

        };

        CTParagraphStyleRef paragraphStyleRef = CTParagraphStyleCreate(paragraphStyles, sizeof(paragraphStyles) / sizeof(CTParagraphStyleSetting));
        return [NSMakeCollectable(paragraphStyleRef) autorelease];

    })());

    NSAttributedString *returnedString = [[[NSAttributedString alloc] initWithString:aString attributes:[NSDictionary dictionaryWithObjectsAndKeys:
        fontAttr, kCTFontAttributeName,
        foregroundColorAttr, kCTForegroundColorAttributeName,
        paragraphStyleAttr, kCTParagraphStyleAttributeName,
        [NSNumber numberWithInt:kCTUnderlineStyleSingle], kCTUnderlineStyleAttributeName,
    nil]] autorelease];

    return returnedString;

}

Think of the many 0.0f as CSS Reset.

Drawing the attributed string with even baselines

If you’re creating an UILabel subclass, this would probably work. Without drawing adjustments, fonts with slightly different ascender and descender values will twiddle around. Which makes an unholy, unsightly mess.

Note that ctFrame is a private property and irCTFrameEnumerateLines is a simple convenience wrapping around functions that operate on a CTFrameRef:

- (void) drawTextInRect:(CGRect)rect {

    if (![self isShowingRichText]) {
        [super drawTextInRect:rect];
        return;
    }

    CTFrameRef usedFrame = self.ctFrame;
    if (!usedFrame)
        return;

    CFRetain(usedFrame);
    CGContextRef context = UIGraphicsGetCurrentContext();   
    CGContextConcatCTM(context, CGAffineTransformMake(
        1, 0, 0, -1, 0, CGRectGetHeight(self.bounds)
    ));

    __block CGFloat usableHeight = CGRectGetHeight(self.bounds);
    CGContextSetTextMatrix(context, CGAffineTransformIdentity); 
    irCTFrameEnumerateLines(usedFrame, ^(CTLineRef aLine, CGPoint lineOrigin, BOOL *stop) {

        usableHeight -= self.font.leading;

        CGContextSetTextPosition(context, lineOrigin.x, usableHeight - self.font.descender);
        CTLineDraw(aLine, context);

    });

    CFRelease(usedFrame);

}

Appendix

gh://schwa/CoreTextToy

Link

The fact that Valve released a Portal 2 OST with Lisp references in song titles alone, explains why Valve is an unique place to work at. You don’t tile Mecca with the finest marble, though. Vestiges of greatness always simmer through the product.

Ship great, but don’t take forever. Make awesomely great products. Some people never get this, and get lost in a sea of mediocrity, others, perhaps, are complacent with meritocracy. Some are trapped in the netherlands, others are zombies from the stone age.

I loathe unnecessary compromises, and this daily fear of becoming a compromiser haunted me. It took a long, long time for me to learn how to be pragmatic, without losing my soul.

Tags: retain cycle
Link

There’s another ld in /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain if you were playing with the latest stuff and can’t build for the Sim.

Link

If I am understanding it correctly: the Web is hot because it delivers stuff that can be effortlessly maintained. NaCl allows delivery of secure and safe binaries by using sandboxes and perfect static analysis. NaCl runs atop a browser (a “host app”), in a world where abstrations no longer matter, performance-wise.

Isn’t it fundamentally the same thing as the App Store and Sandboxing? Right-o, Steve killed the clones. And the Lemmings did not do well at all.

OddlyPowerful

Link

WMF ➡ CGImageRef, because wv and UniConverter are both GPL/LGPL, and GPL/LGPL is evil (“incompatible with the App Store”).

How?

NSBundle *ownBundle = [NSBundle bundleForClass:[self class]];
NSString *wmfPath = [ownBundle pathForResource:@"Image" ofType:@"wmf"];
NSData *wmfData = [NSData dataWithContentsOfMappedFile:wmfPath];

IRWMFDocument *document = [IRWMFDocument documentWithData:wmfData];
CGImageRef fullResolutionImage = [document newFullResolutionImage];

UIImage *image = [UIImage imageWithCGImage:fullResolutionImage];

if (fullResolutionImage)
    CFRelease(fullResolutionImage);

return image;
Text

IRTextAttributor

IRTextAttributor is a simple class that solves the problem where I’d like to attribute a certain string asynchronously. For example, given the string:

Google.com is here.

I’d like it to eventually look like:

Google.com (“Search the world’s information, including webpages, images, videos and more. Google has many special features to help you find exactly what you’re looking for.”) is here.

The idea is to create an attributor which works synchronously, that has two primary worker blocks.

The first worker block is called the Discovery block, which goes thru all the characters, and reports ranges of substrings to a callback block, describing prospective items of interest.

The second worker block is called the Attribution block, which is also handed a substring and a callback block. The block will do its own work, probably thru an Embed.ly invocation, or probably thru reading from a file, and when it’s done, call its callback with the final attribute value, or nil if it can’t find one.

The attributor holds a mutable attributed string as a property, and every time the property changes, it reevaluates the entire string, skipping work on known substring-attribute pairs. Its delegate object, conforming to <IRTextAttributorDelegate>, will be notified whenever a new attribute is found and inserted to the “master” attributed string.

To use the object, you can create an instance, then take advantage of IRTextAttributorDiscoveryBlockMakeWithRegularExpression(), which takes an NSRegularExpression object. Then, assign an attribution block, which takes a string and a callback:

textAttributor.attributionBlock = ^ (NSString *attributedString, IRTextAttributorAttributionCallback callback) {

    if (!attributedString) {
        callback(nil);
        return;
    }

    NSURL *url = [NSURL URLWithString:attributedString];
    if (!url) {
        callback(nil);
        return;
    }

    [[WARemoteInterface sharedInterface] retrievePreviewForURL:url onSuccess:^(NSDictionary *aPreviewRep) {

        callback(aPreviewRep);

    } onFailure:^(NSError *error) {

        callback(nil);

    }];

};

Then, assuming you have a text view, use some localized event coalescing in -textViewDidChange:

- (void) textViewDidChange:(UITextView *)textView {

    NSString *capturedText = textView.text;

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.25f * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void){

        if (![textView.text isEqualToString:capturedText])
            return;

        self.textAttributor.attributedContent = [[[NSMutableAttributedString alloc] initWithString:capturedText] autorelease];

    });

}

The coalescing also prevents issue with the attributor working overzealously on every single keystroke. I tried using NSRunLoop methods which are probably higher level, but did not get them to work at the first time. :p

One thing I learned when writing this class, is that attributed strings don’t only contain attributes to style the text. They can contain almost any Objective-C object, and the fact can be very well-exploited.

Video
Text

Inbound Taste of Code

What makes Jobs memorable is different from what makes Ritchie memorable. Ritchie introduced building blocks for the modern world, but Jobs (or people who worked with Jobs) took them and built something directly manipulatable with them. What made Jobs great is not about grand paradigm shifts, but relentless polish concentrating on the front-end.

What’s wrong with many technology solutions is not that they won’t work, but that they are inelegant. Ugly stuff are ephemeral and will not be missed when they are gone. Elegant stuff, even if they don’t work as efficiently, are generally left in place as long as they are adequately performant. We write wrappers around difficult-to-use frameworks. Abstractions are created, generally with great performance penalty. The underlying layer might be totally fine, usually covers more stuff, but they are inefficient to the human brain, and are therefore more ugly and inelegant.

The ugly is left unchanged for several reasons: that the problems they solve are uninteresting, troublesome and disattractive, replacing the solutions cost too much to be lucrative, or that they’re not needed to be sexy — because they already worked well enough.

Design no longer matters when the object no longer directly touches people. Similarly, taste no longer matters when the technology stack is wrapped in layers of abstractions. As long as it is out of sight, it is out of mind. For serious craftspeople, there aren’t many chances to get things right. Design errors in commercial projects, where lines of code are directly built with dollars, errors in the design process will haunt the project until its death.

I think what’s above explains a) how much I hate in-band communication happening right within RTF 1.5’s image attachments and how much I think Bundles are the right way to go twenty years ago, and b) why agile development is hot.

Tags: rant
Text

How long did it take you from judging Objective-C’s eerie square brackets in curious eyes, to mastering the language or even using it exclusively in professional projects?