Swanros.com

Notes on stuff, and thoughts on software development.

› Google got it wrong. The open-office trend is destroying the workplace.

Completely agree. From The Washington Post:

As the new space intended, I’ve formed interesting, unexpected bonds with my cohorts. But my personal performance at work has hit an all-time low. Each day, my associates and I are seated at a table staring at each other, having an ongoing 12-person conversation from 9 a.m. to 5 p.m. It’s like being in middle school with a bunch of adults.

› Checking for the presence of an optional method in a protocol in Swift

Pretty cool.

import Foundation
    
    @objc protocol Foo {
        optional func say() -> String
    }
    
    class Doesnt: NSObject, Foo {  
    }
    
    class Does: NSObject, Foo {  
        func say() -> String {
            return "hi"
        }
    }
    
    let doesnt: Foo = Doesnt()  
    let does: Foo = Does()
    
    if let f = doesnt.say {  
        f() // Never called
    }
    
    if let f = does.say {  
        f() // Returns "hi"
    }
    

Strategy for consuming a horrible API

As most of the apps, the one I'm currently working on calls to a web service on a regular basis.

The big issue here is that these calls are made to URLs that, while are part of the same API, do not have any structure nor are versioned.

For instance, the authentication URL looks something like http://host.com/u/login, but the URL that lets me download resources from the server to display on the app looks like http://host.com/mobile/v2/resource. Within the same app, I often have to call http://host.com/api/v3/resource too1.

So, you see, these URLs are a mess. Some are prefixed with /api/, others aren't. Some have version numbers on them, some others don't.

On top of that, the app should be able to point to different hosts on the fly. The login endpoint could be http://host.com/u/login, http://host2.com/u/login or http://host3.com/u/login, and so forth for each of the APIs I have to call2.

What would be the best way to handle this situation?

URLManager

Here's what I'm doing:

// URLManager.h
    #import <Foundation/Foundation.h>
    
    @interface URLManager : NSObject
    + (NSURL *)loginURL;
    + (NSURL *)resourceURL;
    // The rest of the URLs representing different API endpoints.
    @end
    

The implementation looks like (something along the lines of) this:

// URLManager.m
    @implementation URLManager
    + (NSURL *)baseURLWithPath:(NSString *)path {
        NSString *baseString = nil;
        ServerCode serverCode = ... // ServerCode is an NS_ENUM
    
        switch (serverCode) {
            case ServerCodeFirst: {
                baseURL = @"http://host.com/";
            }
                break;
    
            / ** ** /
        }
    
        if (path) {
            baseString = [baseString stringByAppendingString:path];
        }
    
        return [NSURL URLWithString:baseString];
    }
    
    + (NSURL *)loginURL {
        return [self baseURLWithPath:@"/u/login"];
    }
    
    + (NSURL *)resourceURL {
        return [self baseURLWithPath:@"/api/v3/resource"];
    }
    @end
    

So, whenever I need to hit the resource API endpoint, I can get the URL easily:

// This would tipically happen on a class whose only purpose is to make API calls.
    NSURL *resourceURL = [URLManager resourceURL]; // => http://host.com/api/v2/resource  
    

Since the API is not versioned (at least on a realiable or sensitive way), there's no point on creating constants for the version numbers. Once the server side is normalised, that would be a much welcomed change here.

› Why "lazy var" is not "lazy let" in Swift?

On the Apple Developer Forums someone asked that very question and got an insightful answer from Chris Lattner:

The way to think about it is that "let" in Swift's current implementation is about physical immutability, not about logical immutability. Physical immutability means that ones the bits are set in memory (i.e. that the let value is initialized) they can never be changed.

Read the whole response here (needs an Apple Developer account).

› Swift: Increasing Performance by Reducing Dynamic Dispatch

Nifty post from the official Apple Swift blog:

In performance sensitive code [...] overhead is often undesirable. This blog post showcases three ways to improve performance by eliminating such dynamism: final, private, and Whole Module Optimization.