movq

Wherein I Move a Lot of Words Around

Swift

Swift is kind of like when you’re a kid and you fill the bag of jelly beans with all your favorite flavors and then reach in and have a handful all at once. Each was a good idea, but together it lacks anything that made any single piece good.

Swizzling Swift

Swift & the Objective-C Runtime:

Even when written without a single line of Objective-C code, every Swift app executes inside the Objective-C runtime, opening up a world of dynamic dispatch and associated runtime manipulation

With an opener like that, how can you not read (and be both slightly horrified and optimistic)?

A Stanford Education at a NaN of the cost

Developing iOS 8 Apps with Swift - Download Free Content from Stanford on iTunes:

Updated for iOS 8 and Swift. Tools and APIs required to build applications for the iPhone and iPad platforms using the iOS SDK. User interface design for mobile devices and unique user interactions using multi-touch technologies. Object-oriented design using model-view-controller paradigm, memory management, Swift programming language. Other topics include: animation, mobile device power management, multi-threading, networking and performance considerations.

Immutable Mutable

Type 'NSMutableArray' does not conform to protocol 'MutableCollectionType'

I really just have no words for that.

Unusable

Coding in Swift would be much easier if the damned IDE (the only one that you can use for it today) would actually work when editing Swift code.

As it stands, however, Xcode regularly tries to compile while you're halfway through writing a symbol and then leaves the error up there for minutes at a time until you manually tell it to re-build the file. Then if you do something unexpected like actually delete something and then type something new then the syntax highlighting (and general language-based parsing) get boned all to hell and give you nonsense like this:

mis-highlighted code

Even worse is that SourceKit is perma-boned somehow after this so things like option-delete to kill a word wind up removing either half a symbol or the current one and part of the one previous. To get it back you have to close the file and re-open it.

This is Xcode 6.1. Release. Not beta.

This shipped.

Perhaps escaped is a better verb.

Mixed Objects in Swift Collections

At first the idea that a collection in Swift could only be one kind of object bothered me, but I’m slowly seeing a useful pattern emerging from this — one that Obj-C made tedious due to its grafting of an pass-by-reference-only object pattern on top of another language.

In the specific case that I just solved, for example, I have a table controller with a static list of choices and actions that would be performed when clicked. In Obj-C I’d probably do something like:

NSArray *choices = @[
    @{ @"name": @"Item 1", @"image": imageForItem1, @"action": @"action1" },
    …
];

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    …
    NSDictionary *choice = _choices[indexPath.item];
    [self performSelector:NSSelectorFromString(choice[@"action"])];
    …
}

… or something equally unsafe outside very specific parameters.

Swift, however, makes that a bit more difficult in a lot of ways. However, when writing in Swift it’s temping to do it in “The Swift Way” as well (namely so I can stop writing question marks and wrapping code in conditional optional statements). Therefore I wound up with something more like:

enum MenuAction : Int {
    case Action1
    case Action2
    case Action3
}

struct MenuChoice {
    var name : String
    var image : UIImage
    var action : MenuAction
}

let choices : [MenuChoices] {
    MenuChoice(name: "Action 1", image: imageForAction1, action: .Action1),
    …
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let choice = choices[indexPath.item]
    switch choice.action {
    case .Action1:
        action1()
    case .Action2:
        action2()
        …
    }
}

It’s certainly more safe. It’s quite a bit more verbose and explicit, but those are also the things that make it more safe. Could it be done in Obj-C like this? Mostly, yes. However, you can’t shove a struct into an NSArray and declaring one-off classes for such things is a bit tedious. Compare the above Swift to the following Obj-C syntax:

typedef NS_ENUM(NSUInteger, MenuAction) {
    MenuActionAction1,
    MenuActionAction2,
    MenuActionAction3,
};

@interface MenuChoice : NSObject
@property (nonatomic) NSString *name;
@property (nonatomic) UIImage *image;
@property (nonatomic) MenuAction action;
@end

@implementation MenuChoice
@end

First, there’s the Foundation macro NS_ENUM to deal with. You have to use this one if you want your enum to work in Swift as well as Obj-C. Then there’s the ever-present nonatomic keyword for properties, and then the repetitive @property itself.

Notice that MenuAction, being an NSUInteger, doesn’t get the * to say it’s a pointer. You’ll have to catch that every time you pull this trick, and you’ll get it wrong at least once.

Lastly, there’s the empty implementation to trigger the generation of the properties.

It’s kind of messy, no? Compare, again, to Swift’s version:

enum MenuAction : Int {
    case Action1
    case Action2
    case Action3
}

struct MenuChoice {
    var name : String
    var image : UIImage
    var action : MenuAction
}

Much cleaner, and it does the same thing. Exactly the same thing. Mostly the same thing. There’s one hidden feature of the Swift version: there will not be a nil for any of those properties of MenuChoice. If the struct exists, there will be a valid value inside.

I’m not sure how sold I am on Swift for a lot of things — the loss of dynamism means a lot of things are now less possible — but there are certainly places where it brings a lot of sanity, and that much I do like. I’m still writing about 50/50 between the two languages, but for a language to get to 50% this fast is noteworthy.