Nick Harris

Protocol Oriented Programming

leave a comment »

The term “Protocol Oriented Programming” has been thrown around a ton over the last year. If you’re wondering what it means, here’s an example that I dealt with tonight while working on Euchre…

Problem

Over the weekend I implemented a way to save multiple in progress games and have iCould key/value storage sync them across devices. The initial implementation was pretty dumb and saved any game in progress. This lead to a long list of saved games just in my testing. That’s not a great user experience. The user should make the decision to save their current game or delete it.

In the app the user can start a new game from the regular Game View or they can elect to resume a game which shows the Saved Games View:

Screen Shot 2016 06 06 at 11 03 37 PM     Screen Shot 2016 06 06 at 11 03 52 PM

Both of the views need to be able to prompt the user to save their current game. They both also have different actions once the user makes their decision.

Protocol Oriented Programming Solution

The best way to solve this was to first create a protocol named SaveGameProtocol that has the current GameController that I want to archive:

protocol SaveGameProtocol {

    var gameController: GameController? { get set }
}

 

Next was to add an extension to that protocol that does the save / delete prompting and handles the users decision before invoking a completion handler. This makes the extension very generic. It does its save / delete job but leaves the rest up to whatever SaveGameProtocol adhering UIViewController that wants to call it.

extension SaveGameProtocol where Self: UIViewController {

    func promptUserSaveCurrentGame(completionAction:(()->())) {

        let alertController = UIAlertController(title: NSLocalizedString("save_game_alert_title", tableName: "GamePlay", comment: ""), message: nil, preferredStyle: .Alert)

        let saveGameAction = UIAlertAction(title: NSLocalizedString("save_game_button", tableName: "GamePlay", comment: ""), style: .Default) {
            action in

            if let currentGameController = self.gameController {
                SavedGamesManager.sharedInstance.saveGame(currentGameController)
            }

            completionAction()
        }
        alertController.addAction(saveGameAction)

        let deleteGameAction = UIAlertAction(title: NSLocalizedString("delete_game_button", tableName: "GamePlay", comment: ""), style: .Destructive) {
            action in

            if let currentGameController = self.gameController {
                SavedGamesManager.sharedInstance.deleteGame(currentGameController)
            }

            completionAction()
        }
        alertController.addAction(deleteGameAction)

        presentViewController(alertController, animated: true, completion: nil)
    }
}

 

There is a trick here though. In order to present the UIAlertController using presentViewController we need to make sure the caller is a UIViewController subclass. That can be enforced by using a where clause on the extension:

extension SaveGameProtocol where Self: UIViewController

 

The last step was to set both my views to conform to the SaveGameProtocol then call the extension with whatever code each needs to continue.

Screen Shot 2016 06 06 at 11 20 34 PM     Screen Shot 2016 06 06 at 11 20 20 PM

And that’s it! Shared save game prompting code for any UIViewControllers that needs it!

Swifty!

Hat tip back to Natasha the Robot  for the pattern.

Advertisements

Written by Nick Harris

June 7, 2016 at 5:41 am

Posted in Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: