Categories
Comic Books iOS App Programming

Book Binder Update

My comic book collection iOS app continues to evolve. I continue to strip out features and focus on the core mission: Buy a comic, snap a photo, add it to your collection.

With that in mind the UX now looks a lot like a photo app that has been preconfigured for storing comic book metadata. Here are the most recent screen shots from my iPhone XS Max:

Summary View

The Summary View displays a scrolling list of series. Each series displays the covers you have photographed. Right now I’m using placeholder covers–I don’t actually own the original Superman comics from the 1930s! This is all built with standard UIKit UIViewController and UICollectionView. I’ve added a custom UICollectionReusableView for the header of each section (series) and for the last cell of each collection I’m using a custom UICollectionViewCell.

I sort the comic book covers in each section by ID, which is a mashup of issue number and variant string. I sort these strings using localizedStandardCompare so that issue 2a comes before issue 20. I love localizedStandardCompare because I didn’t have do any work to solve the thorny “sort strings with numbers and letter as if they are numbers” problem.

The custom collection reusable view is mostly there to display the publisher, name, and era of a comic book series but also to host an edit button that brings up an EditSeriesPopoverView.

Popover views are cool but no longer supported as a presentation type by UIKit so you have to manually display them. I use a UIVisualEffectView to blur out the background behind the popover. I love it when I don’t have to write code!

Detail View

Each detail view displays a large image of the comic book cover photo and some metadata around it. The UISwitch sets the alpha of the cover image to 0.3 if false and 1.0 if true–this give you a nice visualization of what you still have in your collection and what you have sold.

The Edit button brings up the EditIssuePopoverView. I’ve figured out how to pass functions so that I can reuse popover views from different buttons: add an issue vs edit an issue. That’s very cool and has ramifications for how hardcoded view controller need to be to views.

Cutting Scope == More Value

This app looks nothing like my initial conception and has far less functionality than I thought I needed. I find this to be true with most apps I download. They do too much and don’t focus enough on their core use-case. Too much scope means the value of an app is diffused like the pixels behind a UIVisualEffectView.

As always you check out my code on GitHub!

Categories
Nerd Fun Programming

Emoji Tac Toe Opened Sourced

Happy Father’s Day!

 

To celebrate my 28th Father’s Day I’ve opened sourced Emoji Tac Toe. It’s actually not a big deal to anyone but me. It’s kinda of scary open sourcing code that you wrote alone and without first cleaning it up. But what the heck. If someone can learn something from this code, why keep it locked away. It’s already been on GitHub for a year. It’s not getting any prettier under lock and key.

You can find the source code at github.com/jpavley/Emoji-Tac-Toe2. And you can download the iOS app on the App Store at John Pavley > Emoji Tac Toe.

You can play Emoji Tac Toe on your iPhone, your iPad, and your Apple Watch. (As long as you are running iOS 9.3 or later.)

I guess I should chat a little bit about the code just in case you want to take a peek.

First

I plan on refactoring the code quite a bit. I want to basically refactor it so that the core is separate from the iOS implementation and I can port it easily to the web and to Android. Maybe Windows too. Who knowns! I’m going to start this process by adding unit tests and then by tearing it apart.

Second

I plan on updating the code for iOS 11, including Swift 4 and ARKit. I’ve been meaning to add multiplayer over BlueTooth and MessageKit capabilities. I also want to complete the tvOS and macOS implementations.

Third

The core code lives in the EmojiTicTacToe.swift file. Since there are more emoji than I can count I have cherry picked the 1100 that I wanted to include. This is still too many and I should cut it down further. It’s too many emoji because choosing which emoji to play with is difficult. I can’t use Apple’s keyboard user interface because I can’t restrict it to just showing emoji. And I don’t want to waste my time recreating Apple’s design. Also, this game is not about typing anything so a keyboard doesn’t make sense.

Instead I create an array of emoji and it works very well. iOS is great at dealing with Unicode.

Tic Tac Toe is an ancient game and simple. There only eight winning vectors. So, it’s easy to brute force and just check any board for the eight vectors.

As emoji are text it’s simple to translate a game board into a string and back. Interoperability with messaging and tweeting is free. This is why I love emoji! Rich graphics without the cost of image file management. Once day when operating systems allow custom emoji we’ll stop using PNGs and JPEGs altogether. On that day the web will be more fast and safe than ever!

Given the simplicity of the game, my AI is equally simple. When it’s the AI’s turn, I look for an open cell, look for a blocking move or look for a winning move using the eight winning vectors as my guide. Because tic tac toe is too easy to prevent absolute boredom I add a bit of random error into the AI’s thinking so that if the player is paying attention she can beat the machine.

Four

ViewController.swift contains iPhone/iPad specific code.

I found I needed some iPad specific code to avoid a crash when presenting Apple’s standard share UIActivityViewController. I did not open a radar.

I handle several gestures that I’m sure my players never discover but they are there none the less:

  • A long press on an emoji can trigger an attack if battle mode is enabled. A few emoji will do cool tricks in battle mode. There are several battle mode strategy functions that implement these tricks. My favorite is youWin which lets the other player win.
  • Panning up and down turns sounds on and off. That should be a standard gesture for all games!
  • A shake starts are new game with a random pair of emoji. This is the best way to start a new game as choosing particular emoji is a pain.

Five

NewGameViewController.swift contains the code for the game settings on the iPhone/iPad.

Originally, I had the iPhone and Watch Extension collaborate so that one could control the other. But the effort was not worth the reward. Now the two version are completely independent.

I use a UIPickerView with two components to enable the player to choose two emoji. It’s not bad at all if there were only 20 or 30 emoji. But it’s just too much spinning to find a particular emoji out of 1100!

If the user tries to choose the same emoji for player 1 and player 2 (or the AI) I detect that and have the UIPickerView jump to the next emoji. See ensureRowsAreUnique(component: row:).

To make finding a particular emoji a bit easier I allow the player to jump over groups of emoji in the UIPickerView by tapping on the labels for each player. I’m guessing nobody would ever find this feature but the labels are colored blue to indicate they buttons.

Six

InterfaceController.swift contains the code for a very simple version of Emoji Tac Toe that runs on watchOS. I actually like this version if the game best. No battle mode, no sound, no popovers, no choice of emoji. Just a single player game you tap out on your watch while waiting for the train.

Programming the UI for watchOS reminded me of my VisualBasic days! Each button view has it own handler function. No way to aggregate the touches and dispatch them with a switch statement!

Final Notes

All-in-all this code is pretty rough and need a lot of work. But it does work and hardly ever crashes. So that’s something. There is a half-finished tvOS implementation but I’m going to rethink it so don’t look at it!

I had to delete the sound effect that I didn’t create myself. Your build of Emoji Tac Toe will not sound like mine. But otherwise you are free, within the MIT License constraints, to do what you like with the code.

Categories
Nerd Fun Programming Tech Trends

JavaScript, Swift, and Kotlin Oh My!

This blog post now lives on http://blog.viacom.tech/2017/05/31/the-co-evolution-of-javascript-swift-and-kotlin/ (and it’s much shorter and better!)

 

Categories
Nerd Fun Programming

Code Markup in Xcode

Screen Shot 2016-05-28 at 12.58.13 PM

I’m working on a fairly large Swift project. Actually no, that’s not quite true. I’m working on a Swift project with a ViewController file that is getting disorganized and out of control. If this keeps up I might have a large project on my hands but right now it’s just a single file that is getting larger than I would like.

Apple provides some quick and dirty tools that make it easy to navigate a single file with specially formatted comments in your code. This functionality doesn’t provide automated documentation like Headerdoc. And that’s fine with me. I like how Headerdoc has become a mash up of Markdown and JavaDoc. My code is just not stable enough for documenting yet.

Happily Xcode’s built-in special comment parser is enough in the early stages of development to help me navigate a large file and remember where the bodies are buried.

Xcode supports the following out of the box:

  • MARK: (your text here)
  • MARK: – (section divider)
  • ???: Question
  • !!!!: Warning
  • TODO: Task
  • FIXME: Bug

Xcode’s special comments mark up the function navigation  pop-up menu so that you can find your questions, warnings, tasks, and bugs in your code without a overtaxing your the private neural network in your skull. Unfortunately you can’t add new special comments and they don’t show up in the Symbol Navigator.

(Using the MARK: comment you can simulate adding your own special comments. MARK: doesn’t add the word MARK: in front of navigation items in the way that the other special comments do (TODO, FIXME, etc.). So you can use MARK: NOTE to navigate to notes in your Swift code if that makes you happy.)

I use the following additional special comments to keep my code organized and consistent. (Xcode will just ignore them unless I prefix each with MARK:)

  • NOTE: (when the function name is not enough)
  • HINT: (a non-obvious reminder about a bit of code)
  • DBUG: (end of line comment marking code that probably should be removed eventually)
  • DEMO: (example usage)
    // MARK: -
    // MARK: Storyboard Actions

    @IBAction func rightSwipeGesture(sender: UISwipeGestureRecognizer) {
        // HINT: previous page
        currentTrainIndex -= 1
        if currentTrainIndex < 0 {
            currentTrainIndex = trainCount - 1
        }
        loadContent()
    }  

    @IBAction func leftSwipeGesture(sender: UISwipeGestureRecognizer) {
        // HINT: next page
        currentTrainIndex += 1
        if currentTrainIndex == trainCount {
            currentTrainIndex = 0
        }
        loadContent()
    }

It would be nice if Apple allowed us to personalize code markup in Xcode. But only after search and ranking in the App Store are fixed and a 1000 other higher priories are done!

Categories
Programming

Identity used to sign executable no longer valid

The last thing I wanted to do on a Sunday morning is write a blog post about an an Xcode executable problem. What I had planned to do is test my most recent Swift 2.0 SpriteKit game on my iPad and iPhone. Last night I got a “Identity used to sign the executable is no longer valid” error when attempting to run my code on a real device. Since it was around midnight I took the message a notification that bedtime had arrived. Besides, a quick search on StackOverflow would surely solve the problem and if I got on SO now I would be up all night nosing around.

This morning I got the same message and found a post on SO that started  four years ago with two pages of answers: The identity used to sign the executable is no longer valid. It’s been viewed 66K times and covers many ancient versions of Xcode. The top answer simply said to restart Xcode. Indeed, restarting, rebooting, or re-installing is always a great answer! So I tried the first two (restarting Xcode and rebooting all my devices) but no joy. And it’s a cheap answer. 99% of computer problems are temporarily solved by powering down and up the server or device but the root cause sits like a malignant elf in the machine, biding it’s time, ready to strike again.

So I figured it out. My problem, in any case.

Last week I was giving a talk at SUNY Buffalo (shout out to Prof. Hartloff). It’s just far enough away from NYC that I had to stay overnight. I took a MacBook Pro that I don’t ordinarily use for development. When I was working on my new game and testing it my iPad and iPhone (to get actual frame rates and the feel of touching the screen) Xcode discovered that I didn’t have an iOS development certificate on that MacBook and asked me if I wanted to revoke my current cert or copy it over from another machine. Since I didn’t have it I said revoke. Xcode did what ever it does and created me a new iOS dev cert associated with that particular MacBook Pro.

Note to Apple: There has to be a better way for Apple certified developers to manage their certificates in this age of clouds and connectivity. Can’t these certs reside on Infinite Loop server?

Enough backstory!

If you get the dreaded “Identity used to sign executable no longer valid” error and restarting your Xcode doesn’t work here are the steps that should fix it for good.

Go to your Apple developer account certificate overview and read carefully and completely about how to manually manage certs and provision devices. Once you understand what you need to do it’s relatively simple.

  1. Revoke and delete all the could certs and profiles of devices you no longer own that have build up over the years. Clean it all up.
  2. Then, following the instructions from Apple recreate your iOS development and distribution certificates.
  3. Re-provision your iOS devices.
  4. Download your certs and provisioning files and reinstall them into your Mac’s keychain.
  5. Clean and build your app.
  6. Now it should run on the iOS devices you’ve provisioned nicely.

Note to You: Xcode is no longer managing your certs and profiles. But that’s OK. It was doing a bad job anyway.

Post Script

Why didn’t I post this info to Stack Overflow? Because this is a pretty radical solution, not without risk. SO, for better or worse, has been come the place for copy and paste solutions that have not aged gracefully over time. Don’t get me wrong–I love Stack Overflow, recommend it, and use it all the time. But sometimes it’s not safe to post an answer to a problem that requires reading comprehension.

Lucky for you and me, my unpopular blog post will probably be the last item in your search for solutions to apple certification problems.

Categories
Nerd Fun Programming

Four Tips for Xcode Storyboard Users


Apple’s Xcode Storyboard is both your best friend and your worst enemy when it comes to developing state-of-the-art iOS, Mac OS X, tvOS, and watchOS apps. Sometimes, what would be really hard, like associating a function with a gesture is quick and easy. Sometimes, what should be easy, like toggling a property, requires hunting down a checkbox in an inspector that only shows up with the proper object selected.

Below are three common problems with Xcode Storyboards and what works for me to resolve them. Xcode Storyboard evolves with every release: these tips work for Xcode 7.1.1.

1. Is your Storyboard rendering as XML source code and not graphics?

Screen Shot 2015-11-23 at 9.56.10 AM

Somehow, someway Xcode magically switches the view of a storyboard from Interface Builder – Storyboard to Source Code. No matter, just secondary-click on the name of the storyboard in the Project Navigator and select Open As -> Interface Builder – Storyboard.

What is an Interface Builder? Back when the Mac OS X was the NextStep OS Interface Builder was a developer tool for creating views. This ancient app lives on the deep sub-basement of Xcode and sometimes unexpectedly appears.

2. Is your app blank in the simulator?

Screen Shot 2015-11-23 at 8.57.25 PM

It might be that you need to select your main view controller in Main.storyboard and set the “Is Initial View Controller” checkbox in the Attributes Inspector.

This usually happens when you have deleted the default view controller on a storyboard. You know, when you want to start over.

If the default storyboard is still around you can drag the Storyboard Entry Point arrow from the original view controller to point to your main view controller.

3. Having a hard time control-dragging between UI objects and the Document Outline?

Screen Shot 2015-11-23 at 9.13.06 PM

You’re not alone! You can use the Connections Inspector to drag-create connections without holding down the control key.

In the inspector just drag from the circle to the controller that you want to your UI object connected with.

Make sure you have the correct UI object on the storyboard and/or in the Document Outline selected so you connect the right things together.

4. Auto layout constraint values driving you batty?

Screen Shot 2015-11-23 at 9.14.46 PM

Setting up constraints is one of the most unintuitive parts of Xcode’s storyboards. Part of the problem is there a several ways to do it and Xcode doesn’t always seem to do what you ask it to do. Don’t worry! You can use the Document Outline to selection each individual constraint and adjust it’s values in the Size Inspector.

Generally I use the Align or Pin menus to initially set the auto layout constrains for an UI object.

Then I use the Resolve Auto Layout Issues menu to make the UI object conform to the initial constraint values with Update Frames.

Finally, since the UI object always looks weird I select each constraint in the Document Outline, adjust it in the Size Inspect, or delete it and start over.

There you go Xcoders! If I thinking of anything else I’ll update this post!

Categories
Nerd Fun Programming

Fun with Core Graphics and Swift Part 2

Screen Shot 2015-11-09 at 9.24.06 PM

Hey, you have 10 minuets, don’t you?

Then you can add pinch and rotate gestures to our fake-genigraphics app. I didn’t realize it would be this easy. But sometimes Apple’s developer tools engineering team does something amazing–and gesture recognizers are super amazing.

A good way to start is to read the UIGestureRecognizer Tutorial on Ray Wenderlich’s website. I’ve said good things about Ray before. I don’t know him. However, Ray and his team of technical authors just have a way of spelling things out 100 times more clearly than Apple’s developer documentation.

After you’ve read the tutorial open up ViewController.swift in the fake-genigraphics project. Delete the boilerplate code in the ViewController class and replace it with the following code (from the tutorial):

    @IBAction func handlePinch(recognizer : UIPinchGestureRecognizer) {
        if let view = recognizer.view {
            view.transform = CGAffineTransformScale(view.transform,
                recognizer.scale, recognizer.scale)
            recognizer.scale = 1
        }
    }
    
    @IBAction func handleRotate(recognizer : UIRotationGestureRecognizer) {
        if let view = recognizer.view {
            view.transform = CGAffineTransformRotate(view.transform, recognizer.rotation)
            recognizer.rotation = 0
        }
    }

Each of these functions is decorated with the @IBAction tag. That means we’re going to hook them up to events from our project’s Main.storyboard. This part still vexes me. I want to do everything in code and not use drag and drop to wire up events with functions (and properties with variables). Especially since I am left handed and to do a key part of the drag and drop I have to use the control key which only exists on the left side of my nifty Apple Magic Keypad.

Enough whining. Time to drag and drop!

Open up your Main.storyboard in the fake-genigraphics project. In the Object Library on the right find the section near the bottom with all the gesture recognizers. Drag a Pinch Gesture Recognizer out from the library and drop it on the BackgroundView in the storyboard. Now for the hard part: In the Document Outline on the left control-drag the Pinch Gesture Recognizer entry up and drop it on the ViewController entry. On the pop-up menu that suddenly appears choose Sent Actions Handle Pinch. (So weird).

Do these same steps again with the Rotation Gesture Recognizer. What you are doing is connecting events from the gesture recognizers to the functions in the ViewController marked with @IBAction.

Guess What? You’re done! Run your app in the simulator and on your iPhone or iPad. You can now zoom in and out and rotate the Background View like a pro. Notice how responsive and smooth the animation is. Alas there seems to be limits on how far you can zoom out. And you can’t rotate and zoom at the same time. I have trouble with rotating with my left hand. I’m convinced that nobody at Apple is left handled!

Categories
Nerd Fun Programming

Fun with Core Graphics and Swift

Screen Shot 2015-11-07 at 12.15.12 AM

A long time ago in a galaxy far, far away… I was a computer graphics artist. Specifically I was a Genigraphics
console operator. I worked the night shift creating illustrations and slides with vector graphics for big corporations. This was the early 1980s and fast, cheap personal computers with color graphics had not quite been invented yet. Later when I learned to program the Apple Macintosh I had a head start–I had created hundreds of vector images using computer graphic primitives by hand! The ability to draw lines, circles, and rectangles with code blew my mind.

I’m thinking it would be fun to do some graphics exercises with Swift and Apple’s Core Graphics. Maybe recreate some of those Genigraphics images from 30 years ago. Somewhere in the basement I have a box of 35mm slides and 8″ floppy disks. Probably not readable but I should be able to create a few images from memory. Genigraphics was the ancient ancestor of PowerPoint and Keynote. Every element in an illustration or on a slide had to be created from a graphic primitive. A gradient color fill was created with 30 or 40 overlapping rectangles, each with an incrementally different color.  And remember all the primitives were created by a human hand!

One of the most time consuming effects involved creating a grid for a background. It involved much duplicating, aligning, and counting.

So let’s create a clunky Genigraphcis grid in Swift using Core Graphics and display it in a UIView on and iOS device!

Launch Xcode and create a new iOS single view application. Make sure you choose Swift as the language. It doesn’t matter what you call your app. Run the new blank app just to make sure Xcode did it’s job.

Kill the app and go back to Xcode. Create a new iOS Cocoa Touch Class source file. Call it BackgroundView and make it a subclass of UIView. Go to your main.storyboard and select the View in your View Controller. In the Identity Inspector set the class of the View to BackgroundView.

Run the app again just make sure it builds and then kill it and return to Xcode.

Select BackgroundView.swift. You should see a drawRect function provided by Apple. Delete all the comments so it’s ready for some grid code…

override func drawRect(rect: CGRect) {

}

This function is called whenever iOS needs to paint your view on the screen. The rect is the area that needs to be painted. The first time drawRect is called the rect is the same size as your view. Later on when drawRect is called the rect is just the area of the view that needs to be updated. So I get the view width and height from the bounds. I’m also assuming the origin (left, top corner) is always 0,0. Add the following code to your drawRect function so you can get the the bounds width and height and compare it to the rect (technically called the “dirty rect” because that is the part of the view that needs to redrawn).

        let viewWidth:CGFloat = self.bounds.width
        print("viewWidth \(viewWidth)")
        print("rect.size.width \(rect.size.width)")
        
        let viewHight:CGFloat = self.bounds.height
        print("viewHight \(viewHight)")
        print("rect.size.height \(rect.size.height)")

I like to define all my important variables together near the top of my functions because I always know where to find them. Swift let’s you declare and define variable throughout the code. (I only use that freedom for unimportant “throw away” variables that are used inside loops and other control structures.)

Add the code to define your gridlines starting points, lengths, and line width.

        let x1:CGFloat = 0.0
        let x2:CGFloat = viewWidth
        
        let y1:CGFloat = 0.0
        let y2:CGFloat = viewHight

Core Graphics likes all your coordinates to be CGFloats. Since the resolution of an iOS device can be just about anything size these coordinates represent an idealize space as points. On a high resolution iOS device, like an iPhone 6s Plus you’re going to get 3 pixels for every point. My iPhone 6 Plus has a resolution of 1242 × 2208 but Core Graphics gives me 414 × 736 to work with. I’m just going to live with that for now.

I want a nice square grid so I use the either the viewWidth or viewHeight (which ever is smaller) divided 15 as the length of a grid cell.

        let cellLength:CGFloat = min(viewHight, viewWidth) / 15
        print("rowHeight \(cellLength)")

Now it’s time to set the style of our lines: color and width. As I recall Genigraphics only had 64 colors or maybe 128. I’ll figure that out next weekend. In the meantime I choose blue with a width of 2.

        let lineWidth:CGFloat = 2.0
        
        let context = UIGraphicsGetCurrentContext()
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        
        let components: [CGFloat] = [0.0, 0.0, 1.0, 1.0]
        let color = CGColorCreate(colorSpace, components)
        
        CGContextSetLineWidth(context, lineWidth)
        CGContextSetStrokeColorWithColor(context, color)

Wow! That’s a lot of code just to set the color and line width. It’s a little complicated because Core Graphics is context-based. You have to get the current graphics context and modify it to draw. In the code above I’m also creating a color the hard way via a color space and RGBA (Red Green Blue Alpha) color values. All this work will let me have a fine degree of control of the color of the gridlines later on.

Finally, I’m going to draw my horizontal and vertical gridlines!

        // draw horizontal lines
        var i:CGFloat = 0.0
        repeat {
          
            CGContextMoveToPoint(context, x1, cellLength + i)
            CGContextAddLineToPoint(context, x2, cellLength + i)
            
            i = i + cellLength
            
        } while i < rect.height - cellLength
        
        
        // draw vertical lines
        var j:CGFloat = 0.0
        repeat {
            
            CGContextMoveToPoint(context, cellLength + j, y1)
            CGContextAddLineToPoint(context, cellLength + j, y2)
            
            j = j + cellLength
            
        } while j < rect.width - cellLength

I’m just fooling around at this point so I don’t know if two repeat loops is the most efficient way to draw a grid. Right now I’m just happy to see a grid show up. I’ll optimize it later–if needed! To draw my lines I start at 0 and draw each line a cellLengh apart. CoreGraphics is a bit like Logo’s turtle graphics: I have to add drawing commands to the context, building up the image step by step behind the scenes.

If you run the code that this you will see nothing! Go ahead… I dare you!

That’s because you need to tell the graphics context to blast your drawing commands from the context on to the view. One line of code does it.

        CGContextStrokePath(context)

If you have been typing along you now have a custom UIView that draws a grid properly no matter now you hold your iPhone.

If you want to see the grid on your storyboard add

@IBDesignable

just above the class declaration. But be careful! Buggy Core Graphics rendering can freeze up Xcode. (It happened to me while writing this code.) I keep @IBDesignable commented out until I know my drawing code is working.

You can find all the code on GitHub.

Next week I’ll add some more complex drawing in the OG Genigraphics style. This is a good start for your own explorations. Have fun and don’t worry! You can’t blow up your computer by writing code.

Categories
Nerd Fun Programming Uncategorized

The Secret to Swift is Enums

I’ve found the CS193P (Developing iOS 8 Apps with Swift) iTuneU class really helpful in wrapping my old Objective-C head around Apple’s new Swift programming language. Yes, I know we’re at iOS9 but the fundamentals of the class are still relevant and coaxing the code to compile in iOS 9/Swift 2.0 is a fun little last in and of itself.

The big revelation for me is how core Swift’s enums are to understanding and using the language properly. When Apple decided to improve it’s development environment it could have done so in a million different directions. Apple could have just patched up Objective-C. Apple could have moved over to Java or Scala or even JavaScript. (I was hoping for  JavaScript as Node.js and ECMAScript 6 have proved that JavaScript is an industrial strength language with a real future.)

So when I learned that Apple created a new language for iOS and Mac OS X (and now WatchOS and tvOS) application development I was intrigued and disappointed and hopeful all at the same time. Many parts of Swift seems easy and cool but some parts were down right intellectually challenging: Classes and Structs? Super fancy Enums? Optionals? Strings with out a simple function to get their length? What the heck is going on here?

Swift seemed promising. But it was also changing rapidly over the last year. I fooled around with it but when I hit optionals and weak references I realized the language was not going to sugarcoat the problems of null pointers and memory management–it was trying to make them more tractable.

Optionals were especially vexing. var amount: Double? was not a Double. It was a potential Double. Amount! had better be a Double or it would crash my program. If it was’t for Xcode’s automated static code analysis I never would have been able to put the ? and ! in the right places after the right variable names. And I didn’t like that feeling.

But then I found CS193P and Professor Paul Hergarty’s remarkable ability to explain things simply.

Enums in Swift are amazing little machines. They have little in common with C Enum other than you can use them to define collections of related constants. Enums are types with values that evaluate to themselves. But  you can associate a “raw value”, like a number or a string, or more a advanced value, like Tuples or Arrays or Dictionaries. And with advanced types come functions and closures.

Yikes. These are not your father’s Enums. As Professor Hergarty’s says, Swift Enums are types used for when you want to switch between values. And, point of fact, Swift Enums are defined like a Switch structure with case statements. Each of the cases, except with raw values, can be of different types.

And boom! That explains Optionals. When you have a value that could be nonexistent or of some type, an Optional is just an Enum that wraps up it safely so you can pass it around without crashing. ? and ! are just syntactic shortcuts for accessing the different states an Optional variable might be in. Imagining that Optionals are Enums gave me the handle my mind needed to process the whole concept.

In CS193P Professor Paul Hergarty uses an Enum to power his “Calculator Brain”. In any other programming language an Enum would be used to make the code more readable. But in Swift you can use an Enum as the glue to associate states with types with functions. I have a feeling that this Enum-driven mechanism is the cleanest way to write a Swift state machine. It’s still a little rough around the edges and verbose. But it’s a super reusable pattern good not only for the mathematical operations of a calculator but for managing the states of a web server, business application, or game.

//: Playground - noun: a place where people can play

import UIKit
import Foundation

class CalculatorBrain {
    
    enum Op: CustomStringConvertible {
        case Operand(Double)
        case BinaryOperation(String, (Double, Double) -> Double)
        
        var description: String {
            get {
                switch self {
                case .Operand(let operand):
                    return "\(operand)"
                case .BinaryOperation(let symbol, _):
                    return symbol
                }
            }
        }
    }
    
    var opStack = [Op]()
    var knownOps = [String:Op]()
    
    init() {
        func learnOp (op: Op) {
            knownOps[op.description] = op
        }
        
        learnOp(Op.BinaryOperation("*", *))
        learnOp(Op.BinaryOperation("+", +))
        learnOp(Op.BinaryOperation("-", {$1 - $0}))
        learnOp(Op.BinaryOperation("/", {$1 / $0}))
    }
    
    func evaluate() -> Double? {
        let (result, _) = evaluate(opStack)
        return result
    }
    
    func evaluate(ops: [Op]) -> (result: Double?, remainingOps: [Op]) {
        if !ops.isEmpty {
            var remainingOps = ops
            let op = remainingOps.removeLast()
            
            switch op {
            case .Operand(let operand):
                return (operand, remainingOps)
            case .BinaryOperation(_, let operation):
                let op1Evaluation = evaluate(remainingOps)
                if let operand1 = op1Evaluation.result {
                    let op2Evaluation = evaluate(op1Evaluation.remainingOps)
                    if let operand2 = op2Evaluation.result {
                        return (operation(operand1, operand2), op2Evaluation.remainingOps)
                    }
                }
            }
        }
        return (nil, ops)
    }
    
    func pushOperand(operand: Double) -> Double? {
        opStack.append(Op.Operand(operand))
        return evaluate()
    }
    
    func popOperand() -> Double? {
        if !opStack.isEmpty {
            opStack.removeLast()
        }
        return evaluate()
    }
    
    func performOperation(symbol: String) -> Double? {
        if let operation = knownOps[symbol] {
            opStack.append(operation);
        }
        return evaluate()
    }
    
    func showStack() -> String? {
        return opStack.map{ "\($0)" }.joinWithSeparator(" ")
    }
}

var cb = CalculatorBrain()

print(cb.knownOps)

cb.showStack()
cb.pushOperand(1)
cb.pushOperand(2)
cb.performOperation("+")
cb.pushOperand(3)
cb.pushOperand(4)
cb.performOperation("/")
cb.pushOperand(5)
cb.pushOperand(6)
cb.performOperation("*")
cb.pushOperand(7)
cb.pushOperand(8)
cb.performOperation("-")
cb.showStack()

You should watch all the videos in CS193P to get the full picture. But in the meantime I’ve created a simplified version of Professor Hergarty’s CalculatorBrain suitable for a Swift Playground (above). As you fool around with the code keep in mind the following points:

  • CalculatorBain is a class and when it’s instantiated it’s initializer creates a dictionary of operations that it knows about based on type. You can add more known operations by writing a little code in one place. In the sample code the operations for addition, subtraction, division, and multiplication are written very concisely using Swift’s shortcut syntax for closures with default parameter names. (This reminds me of the best features Perl.)
  • The custom type Op is an Enum that is self documenting and has values associated with either a Double (for operands) or a Dictionary (for operations indexed by name). So simple lookups via a case statement are all that is needed to process input and output a result.
  • The two Evaluate functions are recursive, calling each other until every operand or operation needed in the Ops stack is consumed. Evaluate basically does this:
    • Until the Ops stack is empty pull an item off the end of the stack.
    • If that item is an Operand return it and the remainder of the Ops stack.
    • If that item is an operation dig into the Ops stack until you can get two operands and then execute the function associated with the operation using the operands.
    • The return the result with the remaining Ops stack.
  • If I had to write this code without using recursion and without Swift’s muscular Enums, well, there would be a lot more code and it would be more “hard coded”.

The only improvement I can think of would be to declare the known operations as a literal Dictionary. But the Swift compiler isn’t ready for that and complains: “Expression was too complex to be solved in reasonable time”. I guess if Swift can’t do something swiftly it doesn’t want to do it at all!

 

Categories
Programming

Nothing Changes More Swiftly than Apple’s Swift Syntax

Screen Shot 2015-09-24 at 6.39.39 PM
Look at that beautiful Apple Swift code on the right with closures and shorthand argument names! Make’s me smile every time!

I’m enjoying the Stanford University class CS193P: Developing iOS 8 Applications with Swift. It’s free on iTunes U and the instructor Paul Hegarty knows his stuff. He’s a great explainer. I like how first he writes some code in a naive way and then fools around with it, getting it to work and then reworking it like a sculptor with clay. That’s how real programmers work. We write a rough draft of the code, make sure we understand it and then “refactor” it until we’re no longer embarrassed to share it on GitHub.

But even though the class was recorded in 2014 and updated in June of 2015 it’s aging rapidly. We’re already working with Xcode 7 and iOS 9. And all the little minor changes and improvements are adding up.

One problem you might run into is with the second video: More Xcode and Swift, MVC. In this lesson Professor Hegarty wants to show how we can use a form of polymorphism to write clean code. Specifically with Swift supports something that Objective-C did not! In Swift we can have class functions with the same name but different signatures. In the example in the lesson he shows how we can write two versions of performOperation–one that takes two Doubles as arguments and another that takes only a single Double as an argument. Very cool…

Unfortunately this code no longer compiles.

There is an explanation on Stack Overflow (if you can find it). But it’s not really clear as there are a couple of solutions. Perhaps the best solution, like so much on the human side of computer programming, is a matter of taste.

Here is the code and the fix:

    // these functions won't compile with Swift 1.2 and above
    func performOperationWith(operation: (Double, Double) -> Double) {
        if operandStack.count >= 2 {
            displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
            enter()
        }
    }
    
    func performOperationWith(operation: Double -> Double) {
        if operandStack.count >= 1 {
            displayValue = operation(operandStack.removeLast())
            enter()
        }
    }
    // these functions will happily compile
    func performOperationWithTwoOperands(operation: (Double, Double) -> Double) {
        if operandStack.count >= 2 {
            displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
            enter()
        }
    }
    
    func performOperationWithOneOperand(operation: Double -> Double) {
        if operandStack.count >= 1 {
            displayValue = operation(operandStack.removeLast())
            enter()
        }
    }

Because Swift is smart about classes written in Objective-C that you are subclassing from, it forces those subclasses, in this case UIViewController, to obey Objective-C’s limitations. One of those limitation was not allowing polymorphism for methods with the same name but different arguments.

The code is a little uglier, because there is slightly more of it, but it smart of Apple to be as compatible with Objective-C as possible. At least for a few more years 🙂