more info ⬇

@amattn

subscribe for more
stuff like this:

SW engineering, engineering management and the business of software



2011 08 30

@amattn Introduces BeachBin: Baked Blogs in Go

This is the historical, possibly legendary first entry of BeachBin.

BeachBin is a site generator. From the perspective of a napkin’s tush, it holds distant lineage with Jekyll. BeachBin is loosely inspired by Marco Arment’s Second Crack. Having written at least two other “flat file processor”-style site generators, it was time to:

  1. Finally do it right
  2. Learn a new language

As a stalwart promoter of generated or “baked” blogs, the fundamental advantages warm the soul and send the heart pittering. Occasionally, there may even be pattering!

Modern Javascript is able to overcome most of the inherent detriments and deficiencies. The last keystone slid into place with satiating “thunk” when Marco Arment mentioned that Second Crack used Dropbox as its primary mechanism of getting data onto the server.

The advantage of Dropbox, is the removal a large portion of the psychological resistance to writing and publishing. A very software solution to a meat-space weakness.

More on the Go language soon. In order to taunt, tempt and yes, even beguile, I will softly divulge that Go, even in its nascent, embryonic state, is a tremendous productivity multiplier. I wish my competitors to use other lesser means of craft.

2011 09 30

@amattn says Hi

Blog is going live now. Nothing to see in this particular post.

abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz

Just testing line widths. Thank you very much… abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz

2011 10 15

The Disposition of Objective-C

Some observations about Objective C, after over a decade of use.

Verbose

The most mundane of Objective C characteristics. A tautological extreme of syntax is required for basic usage. You get used to it of course. Objective C veterans rely heavily on the IDE and various other tools to assist. The exceptionally handsome and proficient employ a host of apparatus to overcome this particular demon, including snippets, keyboard macros, custom templates and whatnot. Your pinky will stretch like a wet sweater and your square bracket keys will wear out. In the end, the readability of the standard object message redeems and justifies many sins.

Ugly

Objective C is ugly. Take C. Wrap @directives in and around your class structures like a hobo wearing a trashbag. Send Smalltalk in a truck through the front window. Invent properties to clean up a bit. Finish up by flying in pigeons to drop ^blocks over the remains.

I love Objective C dearly. But I will never think of its syntax as clean or pretty.

Readable

Well written Objective C is remarkably readable. Some of this is due to its imperative tendencies. Mostly, the fault lies with its message passing syntax. Being able to intersperse meaning between arguments makes objc about four and a half steps closer towards self documenting.

Message passing syntax is the crown jewel of Objective C.

Compiled

Two big benefits here:

Between the compiler and static analysis, many, many errors can be caught by something not the programmer. The effect is an extra two pairs of eyeballs looking for very mundane and mechanical mistakes.

The second advantage is raw performance. It is the reason why every iDevice from the 3GS onward felt like the Snappiest device of its day.

Ecosystem

Objective C has one company in control of IDE, primary language implementation and the dominant libraries. Like a team with a good coach, Xcode (the IDE), LLVM (the compiler) and Cocoa (the library) are able to cover many of the deficiencies in the language. Furthermore, Objective C is a terrific language in which to write an SDK, framework or library, due to extensibility via language constructs like subclassing, categories, and also at a lower level via the Objective C runtime.

Static, Dynamic or Duck Typed

In practice, your ostentatiously humble author prefers static or duck typing, as overall bug count tends go down over the life of a project. For prototyping or places where you actually need to support a variety of types, id is a dynamic and handy tool. You want it to quack? Formal and informal protocols make it grow feathers.

Momentum

Objective C is aging more like wine than raw eggs. As it matures, we’ve reaped the rewards of properties, blocks, GCD and most recently ARC. No one but the truly inebriated would wager against further improvements. Ask yourself if your most frequently used language gets easier to use every other year.

What is Objective C really lacking?

A motto. I propose:

Objective C: The extensible, readable punctuation-based programming language.

2011 10 18

@amattn's Prospectus of Tools

Last updated August 2013

In no particular order, these are the tools I use regularly:

Apps

Sites & Services

Servers & Stacks

2011 10 19

@amattn and the Recursive Productivity Recipe

  1. Write down the goals you want to be done
  2. Break down each item into sub-items. Write those down.
  3. Either complete an item and cross it off the list, or repeat step 2 with the remaining sub-items.
2011 11 16

@amattn on iOS Prototyping

If you reside in a place where an app prototyping tool famine ravages the landscape, then you don’t live on my planet. Here on Earth, you have at least four mighty options:


Pen & Paper Prototyping

Prerequisites: Pen, paper, preschool education.

Draw your wireframe. Maybe cutout some views to simulate transitions. Go to storytime then take a nap. Not much to say here except that almost every app should start here.

If you are doing a larger project, consider some of the great stencils and sketchpads from UI Stencils. Once you are past brainstorming and into wireframes, they become drift from the land of helpful into the rainbow tinted realm of compelling.

One interesting observation after some paper based UI sessions is an average pen is pretty good at approximating easy click targets for the average human finger. If you can’t write it, it may not fit.

Keynotopia

Prerequisites: Keynote, Keynotopia templates, Half a brain

Keynotopia rings the correct bells and blows the proper whistles. I’ve seen people raise Angel rounds in Silicon Valley based off of demos done with this tool. The whiz bang part is when you open the file on your phone after emailing it to yourself. Instant Device Demo.

You could use PowerPoint, but Keynote is twenty yuu ess dees and overall a less stressful tool when it comes to prototyping. Oddly, the template bundles are now more expensive than Keynote itself…

Briefs

Prerequisites: Some scripting knowledge, Sympathetic soul

Briefs is a nice tool that made the rounds on the interverse for getting rejected by the black hole of the approval process. It’s still a good tool and has been open sourced by the developer after getting jerked around by Apple for so long.

If I were on an elevator, I would describe it as turning images into clickable apps. It’s based on a simple language with the adorable acronym BS. BS is very close to CSS. I’ll wait while you fill this space with the obvious joke. Hahaha nice one!

Like Keynotopia, it’s great for making clickable but ultimately non-functional demos.

Xcode Storyboards

Prerequisites: Xcode 4.2, Objective-C, UIKit familiarity, Tolerance

When Storyboards were announced at WWDC, I was initially skeptical about their benefits over traditional nib files. I’ve since been converted like an indigenous population. I’ve found that in practice, the diminished about of boilerplate is a net win.

Xcode Storyboards really shine however, when doing prototyping work. You can use the built in segues to implement quick, no-code transitions between different screens. It’s a super quick way to stub out the flow of your app.

People scrolling down for the conclusion, START READING HERE!

In practice, you will likely only need one or two of the above tools.

Your own technical expertise may be a limiting factor. The more dev chops you boast, the more options you have.

The other concern is how far into the design process you are.

Paper Prototyping is typically a brainstorming kind of tool. Briefs is aimed at making a quick demo from your brainstormed images, while Kenotopia is something in between. If you have a fairly solid feel for the flow of the app, Xcode Storyboards are great choice, especially given how easily they can be converted to a production project.

Some quick notes on other options:

2011 12 07

ARC Best Practices

Some optional backstory:

The advice here assumes you are using iOS 5 or greater, not 4. In practice, weak pointers are such an important tool in ARC, that I don’t recommend using ARC in iOS 4.

Note on updates

This document has been continuously updated to the very best of my ability since it was originally published back in 2011. The last minor revisions are from 2013 bringing the document current with iOS 7.

General

Bridging

From the documentation:

id my_id;
CFStringRef my_cfref;
NSString   *a = (__bridge NSString*)my_cfref;     // Noop cast.
CFStringRef b = (__bridge CFStringRef)my_id;      // Noop cast.
NSString   *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRef
CFStringRef d = (__bridge_retained CFStringRef)my_id;  // returned CFRef +1

Translated from nerd-speak into slightly-less-nerd-speakish:

NSError

The ubiquitous NSError is a little bit tricky. Typical Cocoa convention is that they are implemented via out-parameters (aka indirect pointers).

In ARC, out-parameters are by default __autoreleasing and should be implemented like this:

- (BOOL)performWithError:(__autoreleasing NSError **)error
{
    // ... some error occurs ...
    if (error)
    {
        // write to the out-parameter, ARC will autorelease it
        *error = [[NSError alloc] initWithDomain:@"" 
                                            code:-1 
                                        userInfo:nil];
        return NO;
    }
    else
    {
        return YES;
    }
}

When using an out-parameter, you will usually use __autoreleasing on your *error object like so:

NSError __autoreleasing *error = error;
BOOL OK = [myObject performOperationWithError:&error];
if (!OK)
{
    // handle the error.
}

If you forget the __autoreleasing, the compiler will simply insert a temporary, intermediate autoreleasing object for you. This was a compromise made under the oppressive regime of backwards compatibility. I have seen some compiler configurations which do not automatically make them __autoreleasing. It is safer to include the __autoreleasing for all new code.

@autoreleasepool

Use @autoreleasepool inside loops that:

Creating and destroying autorelease pools using the @autoreleasepool directive is cheaper than a blue light special. Don’t worry about doing it inside the loop. If you are super-paranoid, at least check the profiler first.

Blocks

In general, blocks just work. There are a few exceptions however.

When adding block pointers to a collection, you need to copy them first.

someBlockType someBlock = ^{NSLog(@"hi");};
[someArray addObject:[someBlock copy]];

Retain cycles are somewhat dangerous with blocks. You may have seen this warning:

warning: capturing 'self' strongly in this 
block is likely to lead to a retain cycle 
[-Warc-retain-cycles,4]

SomeBlockType someBlock = ^{
    [self someMethod];
};

The reason is that someBlock is strongly held by self and the block will “capture” and retain self when/if the block is copied to the heap.

In a less obvious manifestation of the same potential retain cycle, any ivar you use will also capture the parent object:

// The following block will retain "self"
SomeBlockType someBlock = ^{
    BOOL isDone = _isDone;  // _isDone is an ivar of self
};

The safer, but loquacious workaround is to use a weakSelf:

__weak SomeObjectClass *weakSelf = self;

SomeBlockType someBlock = ^{
    SomeObjectClass *strongSelf = weakSelf;
    if (strongSelf == nil)
    {
        // The original self doesn't exist anymore.
        // Ignore, notify or otherwise handle this case.
    }
    else
    {
        [strongSelf someMethod];
    }
};

Sometimes, you need to take care to avoid retain cycles with arbitrary objects: If someObject will ever strongly hold onto the block that uses someObject, you need weakSomeObject to break the cycle.

SomeObjectClass *someObject = ...
__weak SomeObjectClass *weakSomeObject = someObject;

someObject.completionHandler = ^{
    SomeObjectClass *strongSomeObject = weakSomeObject;
    if (strongSomeObject == nil)
    {
        // The original someObject doesn't exist anymore.
        // Ignore, notify or otherwise handle this case.
    }
    else
    {
        // okay, NOW we can do something with someObject
        [strongSomeObject someMethod];
    }
};

Accessing CGThings from NSThings or UIThings

UIColor *redColor = [UIColor redColor]; 
CGColorRef redRef = redColor.CGColor;
// do some stuff with redRef.

The above example has some very subtle problems. When you create redRef, if redColor is never used again, then redColor is destroyed right after the comment.

The problem is that redColor “owns” redRef, and when redRef is accessed, it may or may not be a colorRef anymore. Even worse, is that this type of error rarely shows up on the simulator. It’s more likely to occur when used on a device with lower working memory, like the original iPad.

There are a couple of workarounds. Essentially, you just want to keep redColor alive while you use redRef.

One very easy way to accomplish this is to use __autoreleasing.

UIColor * __autoreleasing redColor = [UIColor redColor];
CGColorRef redRef = redColor.CGColor;

Now, redColor isn’t destroyed until some indeterminate time later, well after the method returns. We can safely use redRef in the scope of our method.

Another way is to retain the redRef:

UIColor *redColor = [UIColor redColor];
CGColorRef redRef = CFRetain(redColor.CGColor);
// use redRef and when done release it:
CFRelease(redRef)

It’s important to note that you need CFRetain() on the same line where you use redColor.CGColor. redColor is effectively destroyed after the last time you use it. The following will NOT work:

UIColor *redColor = [UIColor redColor];
CGColorRef redRef = redColor.CGColor; // redColor is released right after this...
CFRetain(redRef);  // This may crash...
...

One interesting note on the line marked “This may crash” above. Again, in my experience, it doesn’t crash very often in the simulator, but does crash fairly reliably on actual iOS devices. Caveat Developor.

The Big Nerd Ranch has a very deep dive into this issue: http://weblog.bignerdranch.com/?p=296

Singletons

Only incidentally related to ARC. There is a proliferation of home grown singleton implementations (many of which unnecessarily override retain and release).

These should all be replaced with the following:

+ (MyClass *)singleton
{
    static MyClass *sharedMyClass = nil;
    static dispatch_once_t once = 0;
    dispatch_once(&once, ^{sharedMyClass = [[self alloc] init];});
    return sharedMyClass;
}

Every now and then you need the ability to destroy a singleton.
If you are using this for anything but UnitTests, you probably should not be using a singleton.

// declare the static variable outside of the singleton method
static MyClass *__sharedMyClass = nil;

+ (MyClass *)singleton
{
    static dispatch_once_t once = 0;
    dispatch_once(&once, ^{__sharedMyClass = [[self alloc] init];});
    return __sharedMyClass;
}

// For use by test frameworks only!
- (void)destroyAndRecreateSingleton
{
    __sharedMyClass = [[self alloc] init];
}


the fine print:
aboutarchive@amattn
© matt nunogawa 2010 - 2017
back ⬆