Swift first impressions

Technically, it's not a first impression, because the first one was "ugh". But then I read the book and watched all the WWDC videos. Oh boy!

Don't even know where to start, but man, oh man, some stuff is just mind-blowing. Here are a few examples of Operator Overload combined with Generics.

// "test" * 2
@infix func * (left: String, right: Int) -> String {
    var newString = ""
    right.times {
        newString += String(left)
    }
    return newString
}
// testtest

// "abcdef"[2]
subscript(digitIndex: Int) -> Character? {
    var i = 0
    for char in self {
        if i == digitIndex {
            return char
         }
        i++
    }
    return nil
}
// c

// [1, 2, 3] << 4
@assignment func <<<T> (inout left: T[], right: T) {
    left.append(right)
}
// [1, 2, 3, 4]

// view << newSubview
@assignment func <<<T: UIView> (inout left: T, right: T) {
    left.addSubview(right)
}

// emptyDic = ["k1": "v1", "k2": "v2"] + ["k3": "v3"]
@infix func +<K, V> (left: Dictionary<K, V>, right: Dictionary<K, V>) -> Dictionary<K, V> {
    var l = left

    for (k, v) in right {
        l[k] = v
    }

    return l
}
// emptyDic = ["k1": "v1", "k2": "v2", "k3": "v3"]

// emptyDic << ["k4": "v4"]
@assignment func <<<K, V> (inout left: Dictionary<K, V>, right: Dictionary<K, V>) {
    left += right
}
// emptyDic = ["k1": "v1", "k2": "v2", "k3": "v3", "k4": "v4"]

As for iOS 8 goodies ... Check NSHispter's latest post.

Puppet Anthems

This is the second project I've been working on in the past year or so.

It's your fancy and fun way to learn about the national anthems and cultures of many different countries. This is the special World Cup 2014 Edition, featuring all 32 participating nations under one theatrical, vaudeville roof.

Features:

  • professional, in-studio quality performances by citizens from each country, recorded to orchestral backing.
  • inspired animated figures and icons representing individual countries.
  • over 175 cultural icons discussed in detail.
  • historical information related to each anthem.
  • multi-verse lyrics in native and romanized languages, with complete English translations.

Come hear our puppets sing and juggle simultaneously and learn some cool facts at the same time about your own and others' culture.

Soon you’ll be singing along too!

DeinDeal

For the past 6 months I've been working with the guys at DeinDeal on their native iOS app. During this time I worked with some great, creative and really smart people, and I've had the chance to learn a lot.

This is the result, of which I'm quite proud.

LTHPasscodeViewController 3.0.0

You can find it here, or you can just pod update.

When I created the library, I didn't think of making it a cocoapod and all the #define macros and the constants were intended to ease the init: go in the library, customize it once, never think about it again, but after I turned it into a cocoapod, I never thought about the fact that the file gets overridden with every update until recently, when someone pointed it out to me.

3.0.0 comes with a couple of major changes and a few minor ones:

  • All the macros and constants were changed to public properties.
  • Supports pushing, not just presenting as a modal.
  • Supports saving the passcode and timers in a different place than the Keychain. (more details below)
  • Better supports Storyboards and IB. Still not perfect, because I almost never use(d) them, but I hope it's a good start.
  • Has a complete documentation!
  • The labels have numberOfLines = 0.

About the custom saving:

- (NSTimeInterval)timerDuration;
- (void)saveTimerDuration:(NSTimeInterval)duration;
- (NSTimeInterval)timerStartTime;
- (void)saveTimerStartTime;
- (BOOL)didPasscodeTimerEnd;
- (void)deletePasscode;
- (void)savePasscode:(NSString *)passcode;
- (NSString *)passcode;
// All of them fall back on the Keychain if they are not implemented, even if [LTHPasscodeViewController useKeychain:NO] was called, for flexibility over what and where you save. 
// Do you only want to save the passcode in a different location and leave everything else in the Keychain? Call [LTHPasscodeViewController useKeychain:NO], but only implement -savePasscode:

As usual, if you find any problems or any way I could improve the library, please let me know.

Thanks to everyone for the help and for all the suggestions that found their way into this update!

Free and Pro versions

For my first 2 games I had a project for the Pro version and another project for the Free version, and, as everyone knows, that's a huge pain to maintain.

So, at first I created this:

#define kFreeVersion ([[[NSBundle mainBundle] infoDictionary]\
[@"CFBundleIdentifier"] isEqualToString:@"com.rolandleth.appnamefree"])

and added a warning in the App Delegate:

#warning Reminder: Don't forget to check this on every release!
if (kFreeVersion) {
    // do stuff for the free version
}

But this implied, as the #warning suggests, to never forget about manually changing the bundle ID at every release. So searching I went and I found this, then this.

Pretty basic stuff, which I never thought about. I combined the 2 approaches, and now I have 2 targets, but use the above macro instead because I think #ifdefs make the code look ugly.

Combined with this script (I have Run script only when installing checked):

VERSIONNUM=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_FILE")
NEWSUBVERSION2=`echo $VERSIONNUM | awk -F "." '{print $2}'`
NEWSUBVERSION3=`echo $VERSIONNUM | awk -F "." '{print $3}'`
NEWSUBVERSION3=$(($NEWSUBVERSION3 + 1))
NEWVERSIONSTRING=`echo $VERSIONNUM | awk -F "." '{print $1 ".'$NEWSUBVERSION2'" ".'$NEWSUBVERSION3'" }'`
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $NEWVERSIONSTRING" "$INFOPLIST_FILE"

makes releasing 2 versions of an app much easier than what I was used to.

Edit, 10 minutes later: Well, I had to switch to the #ifdef approach, because I wanted to remove all the ad related frameworks from the paid version, so I don't have any troubles with the approval. Oh well...