Learning Swift – The First Weekend
This is part of my Learning Swift series of posts. Please see Super Euchre Swift to understand what I’m building while learning Swift.
I’ve been reading and learning about Swift since I was sitting in Moscone for WWDC 2014 and had the same “No F__king Way!” collective moment with the rest of the Apple Developer World. Ideas like let vs var, generics and even optionals and unwrapping were never hard for me to grasp. That means I think I’ve been OK at reading Swift over the last year but haven’t taken any opportunity to write some myself.
A big part of the reason I held off is Apple’s own statement that the language was going to be changing in big ways over that year. Way back when I first graduated college, there was a new language called C# along with the .Net Framework coming out of Microsoft. Though the first C# book I bought was in 2001, I didn’t ship real C# code until I was at NewsGator in 2005. The differences between the language and the compiler between .Net 1.0 and .Net 2.0 was huge. Microsoft was a fantastic partner in the transition but it was still eye opening to be sitting with a compiler engineer in Redmond trying to figure out why our code was broken.
So I waited. And what I’ve seen both from Apple at WWDC this year and the general buzz in the community has me convinced that now is the time to really jump in.
EuchreCard – Struct or Class
I started this weekend the same way I start every re-write of Euchre… the EuchreCard object. Euchre itself uses common playing cards. Luckily for me, Apple used playing cards in its Swift documentation about nested types.
The first thing that struck me about that sample code was that the BlackjackCard was a struct and not a class. This seems to be one of the fundamental decisions in Swift a developer needs to think through when adding objects to the code base.
I decided to go with struct for EuchreCard. For one, Apple used a struct for BlackjackCard. That’s usually a dead give away. The other was Greg Heo’s (@gregheo) Switching Your Brain To Swift talk at this year’s 360iDev. He had a slide (which unfortunately I don’t see in that post) about Swift foundation and what things are represented by struct vs. class. From what I recall the difference was quite stark in that there were minimal classes and many structs. That leaned me even closer to struct.
The ultimate conclusion I drew was deciding if an object should be passed by reference or by value. In Swift, structs are very much on par with classes. They can have properties, initialization functions, even their own functions. Obviously that’s very different then ObjC. Classes, however, are passed by reference, while structs are passed by value. That boils down to understanding when an object should be mutable and who can change it.
Mutability and type safety are some of the fundamental ideas that Swift is being built on. Pass by value is safer in the aspect that you can pass a value into a sub function without the caller worrying about what its value may have changed to when the sub function returns. That’s not to say mutable objects don’t have their place. They absolutely do. The approach I’ve decided to take with all things Swift is to use the safest option first then move to something thats a little more unsafe once I know WHY I need it to be. So for me that means struct first till I know I need it to be a class.
This is counter to what the Apple docs say, but I was also in the room for the very popular Protocol Oriented Programming in Swift session at this years WWDC. I need to watch that another dozen or so times to really understand it all but in the mean time I like this Stack Overflow answer on Swift Structs vs. Classes.
Suits and Associated Values
The next big decision I came across was how to represent a cards suit and rank. I’ve always used enums for these in the past and Swift didn’t change that decision. It did make it a little more interesting though.
With swift, an enum case can have an associated value. Enums in ObjeC, at least how I have always used them, are always ints. The BlackjackCard however uses a char for the suit. Not only is it a char, but its the unicode character for the typical card suits of hearts, spades, diamonds and clubs. Super clever!
But does clever mean better?
For me it doesn’t. In Euchre, the trump value of a Jack is tied not only to its suit but to the color of that suit. For instance, if trump is Clubs then the Jack of Clubs is the best card in the deck while the Jack of Spade is second. Its because both suits are black, the same way that both hearts and diamonds are red.
In my past code for Euchre I’ve relied on how I setup enums to help test if a card has the same color suit as another by using mod. This means I can do if statements that look like this:
if ((rank == .Jack) && (suit.rawValue % 2) == (trumpSuit.rawValue % 2))
If you’re not familiar with Swift, “rawValue” probably sticks out to you. When you assign an associated value to an enum case you can get its actual value by using rawValue. This allows me to treat a suit’s enum value as an Int in order to call % on it.
So though I could use a clever unicode character for a cards suit enum, I opted to stay with Int.
In my UI layer I have assets for each card that are named by using an abbreviation for the cards rank and suit. For instance, the Ace of Spades has an asset name of AS. The King of Clubs is KC while the Ten of Hearts is 10H.
My old ObjC code used calculated properties to return these to callers dealing with a EuchreCard. A calculated property is one that looks and acts like a property from the callers perspective but uses an internal method to calculate its value whenever its accessed.
Many old school ObjC programmers will tell you that calculated properties are evil and you should always use a function. They have very good arguments why that I typically agree with. Though for me, things like this asset name for a card were a perfect candidate for a calculated property since they made reading the code higher upstream easier on me though I took a small calculation hit on each access of the property.
Lazy Stored Properties
Swift solves this for me though in a very nice way with the introduction of lazy stored properties. Obviously my EuchreCard doesn’t know the name of its asset until it has its suit and rank set. I also don’t need this value right away when creating a deck of cards. I only need it when the UI first needs to display a card.
So instead of declaring a property that needs to be set on init…
(oh did I mention that Swift makes you set a value for all your properties during init? It does and its pretty awesome since it leaves nothing ambiguous up to the compiler/runtime)
…you can declare it lazy and set its value to a function that will be invoked the first time the derived value is needed. This way I can calculate its value once when its needed and have it stored for any point after. Very nice! I did the same with longName which I’ve used in past Euchre versions.
There’s nothing ground shaking or particularly valuable about my EuchreCard so why not share.
Here’s a gist of my EuchreCard struct.
First Weekend Conclusions
I wrote this down in my running Swift notes about 1 am Saturday but I like it:
“ObjC is hard to learn and really hard to learn the “right” way to use it. Swift feels different. The way it overlaps with other languages has made it very easy for me to pick up so far. I thought I would be fighting it more but instead I’m seeing much better ways to implement Euchre’s AI layer. I can see ways I could have done this in ObjC but the look of the code feels much more natural with Swift”
It was a fun weekend! Looking forward to diving in more!