Nick Harris

Ad Rev

leave a comment »

Back in June when I released Super Euchre! and Solitary Solitaire I started an experiment. I wanted to see if the banner ads I had always used in Euchre were worth it or if moving to interstitial ads was a better way to go.

Banner ads are always present. I personally hate them. While I’m using an app they’re always there taking up space the app could be using and ruining the overall design of the interface.

Interstitial ads are ads that overtake the app (sometimes with a timer before you can dismiss them). They’re way more intrusive then banner ads, but they’re also easier to mold to your user experience. An ad that over takes your app in the middle of reading an article is incredibly annoying. Presenting one when you’re in a “paused” frame of mind is more seamless.

With that in mind, Solitaire only shows an interstitial ad after you’re already playing a game but have given up and are trying to start a new one. You’re in a position of change within the app already so pausing your transition for a few seconds to present an ad is the least intrusive opportunity.

Euchre has an always present banner ad.

The Results

I think its hard to deny that interstitial ads are the way to go in my case at this point.

1. They’re less annoying
2. They pay MUCH better
3. They are less annoying and pay MUCH better

Between my two apps, Solitaire has about 10% the install base of Euchre but produces 20% of the overall ad revenue.

Here are the numbers:

Screen Shot 2016 11 30 at 9 20 25 PMScreen Shot 2016 11 30 at 9 48 45 PM

The Plan

I plan on moving Euchre away from the banner ad to an interstitial only on loss this weekend. The impressions will fall off dramatically but the RPM should rocket. Users will have a better experience and I’ll make more per install.

There’s more to digest here but its mid-week and my head is in the middle of a refactor for my day job, but I hope to revisit this.

Those are real numbers though. If you’re better at business math then I am, send me a note about what you think. 

Written by Nick Harris

December 1, 2016 at 5:09 am

Posted in Uncategorized

Apple Watch Series 2

leave a comment »

My friend and old co-worker Brent Simmons on the Apple Watch (cherry picked from a post about Apple in general):

Here’s a case: my wife bought a Fitbit when I bought my Apple watch. I envy her iPhone app which is so much cooler than Apple’s fitness software; I envy her not having to charge her device every night; I envy her not having to wear a heavy thing on her wrist.

And her Fitbit does sleep tracking, which I’d like to do — but my Apple watch is charging while I sleep, and there’s no way I’d be comfortable sleeping with that bulky thing on my wrist anyway.

 I was not a fan of my original Apple Watch. The battery sucked. It was slow. The apps seemed useless. The sports band was uncomfortable. 

When WatchOS 3 came out I started to change my mind. I was part of a team that developed my first professionally released watch app. I also made my own for fun app

So I bought an Apple Watch Series 2 this year instead of upgrading my iPhone (which is a 6S+). I also bought one of the nylon weave bands.

The results?

I put my watch on this morning at 6:45am. Here’s the battery at 9pm:

IMG 3351

For fun I decided to charge it for 20 minutes – about what it would take for me to take a shower and get dressed in the morning:

 IMG 3353

I’ve slept with it on many nights. The band is definitely the difference. I don’t even notice I have it on anymore. I’m more surprised when I look at my wrist and its not there then being annoyed at the band making me uncomfortable.

I also find myself taking time to meet my exercise and move goals everyday. I had a perfect month in October for both. I’m on track for the same in November. Forcing myself to do something that registers as exercise for 30 minutes everyday is pretty easy during the week as I walk ~2 miles to/from the train to the office but on weekends it really drives me to get outside. I’ve been doing 7 miles a day on the bike over the weekend the last two months or doing my own 30 minute workouts in the basement on days when that’s not feasible.

This morning when I saw the Thanksgiving Challenge I was in right away. I’ve been fighting with the idea that I might not hit my goal that day so maybe slipping for a day this month was OK. But now I’m even more driven to keep up the pace.

Is the Apple Watch perfect? No. But I’m happy that the engineering efforts at Apple are being spent on them instead of monitors and routers. I’m an Apple convert that never bought those things anyway. I could get what I needed elsewhere at a better price.

Next up for me I suppose is seeing if CloudKit can replace Dropbox and Flickr.

I don’t really trust in Apple web services…

Written by Nick Harris

November 22, 2016 at 4:43 am

Posted in Uncategorized

Limiting the Number of Lines in a UITextView

leave a comment »

Intro

I have a UILabel in my app that shows a maximum 4 lines of text. If the user taps on it, the view becomes editable and the user can change the text in a UITextView.

Problem

I want to limit the user to only 4 lines when they’re editing the text in the UITextView.

First Attempt – Default Behavior

By default a user can add as many lines of text as they want to a UITextView and the view will update itself to make sure the last line is visible.

This is no good for me since the user can enter more lines then I’m going to show when they’re done editing.

Second Attempt – maximumNumberOfLines

According to the docs for NSTextContainer.maximumNumberOfLines:

The layout manager uses the value of this property to determine the maximum number of lines associated with the text container. The default value of this property is 0, which indicates that there is no limit.

In Xcode 8 and iOS 10 the only effect this parameter has on a UITextView is that the last line after the max is no longer made visible. The user can keep entering text all they want but its no longer visible in the UITextView.

My Fix

The fix I came up with was to count the number of line breaks by using CharacterSet.newLines in textView:shouldChangeTextInRange:replacementText: of the UITextViewDelegate before allowing a user change.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

    let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
    let newLines = text.components(separatedBy: CharacterSet.newlines)
    let linesAfterChange = existingLines.count + newLines.count - 1

    return linesAfterChange <= textView.textContainer.maximumNumberOfLines
}

This works as intended.

But this feels like a hack around a UIKit bug.

Is it?

Written by Nick Harris

September 11, 2016 at 4:41 am

Posted in Uncategorized

Introducing Super Euchre 2.0 and Solitary Solitaire 1.0

leave a comment »

If you’ve been following along with my blog about my re-write of Euchre, my Solitaire challenge and me learning Swift and wondered if I’d ever release them to the App Store, well the wait is over!
(then some thoughts on the last couple of months)

Super Euchre 2.0

Icon 180

https://itunes.apple.com/us/app/super-euchre!/id697411524?ls=1&mt=8

– Brand New Layout and Card Faces
– New Game Replay
– Stats
– iPad Landscape and Multitasking Support
– Stats synchronization between devices

Solitary Solitaire 1.0

Icon 180

https://itunes.apple.com/us/app/solitary-solitaire/id1123243052?ls=1&mt=8

– Single or three card deal
– Auto play a winning hand
– Best time, score and moves
– iCloud syncing of games
– iCloud syncing of best time, score and moves
– Landscape support for iPhone 4S through iPad Pro
– Multitasking support on iPad

Swift

Both apps a written completely in Swift 2.2 from my standpoint. I get that the Objective-C runtime powers them but there is not one line of Objective-C in my repositories. I’ve been writing Objective-C for about half my career at this point (7 out of 15 years) and I still like the language. Its odd and quirky but I can make the devices I love do things with it so its cool by me.

Swift though… I love Swift!

Super Euchre in particular was much easier to code this time around. Higher level functions like sets, map and filter made writing the player logic much easier. I realize now that I could have accomplished the same type of approaches in ObjC using more NSPredicates but in actuality my past code was littered with tons of for loops. The Swift code to me is much easier to read and understand.

After higher level functions, my second favorite aspect of the switch to Swift is how much more I pay attention to mutability. For the player logic I decided to use NSOperations to compute some type of decision. In the past I’d have that code in one monolithic class. Using NSOperations allowed me to concentrate just on one small piece of logic making it easily testable. As far as mutability, all of my operations and even internal functions never mutate any of their input parameters. All operations have a operationResult parameter that holds the computation. No function uses the inout keyword. Even functions that do something as simple as sorting use a return value and @warn_unsed_result to remind myself that none of my functions ever mutate. I really like this approach and plan on using it in the future.

Auto Layout / Adaptive Layout

I haven’t used Xcode 8 yet but what I saw in the Platforms State of the Union at WWDC I think would have made both these games SOOOO much easier to create. If you’ve ever created landscape layouts with size classes you probably know what I mean. Interface Builder in Xcode 7 means working in a canvas that doesn’t have the same dimensions as any device you’re creating it for. Xcode 8 looks like a much better experience.

Multitasking was incredibly simple for both since I was already supporting devices from 4S up to the iPad Pro. Getting the layout right for the other devices meant multitasking was already done. I think users of such stupid time wasting card games will appreciate it!

One thing I did do different with auto layout in both of these games is to use placeholder views in the storyboards then adding all the actual views on viewWillAppear. The placeholder views give me the correct frame when the game starts (and also after rotation or switching multitasking size). What it saved me – particularly for Solitaire – was having every card in play represented on the storyboard. It made all the animations easier. Because the views that I add on viewWillAppear don’t have any auto layout constraints, I can animate their frames instead of updating their constraints (via tons of IBOutlets). I’m not sure that I’d do this very often in the future but this approach worked really well for these games.

iCloud Key / Value Storage

Both games use NSCoding and NSUbiquitousKeyValueStore to sync not only stats and best scores across devices but also unfinished games. I’m still not sold on this. It works well enough that I don’t think most people will notice how long the lag between synchronizing on one device and getting the update on another device can really be. I’m guessing in real world use, the 1 to 5 minutes won’t be noticed. We’ll see. I have a feeling this will be the biggest source of complaints and bad reviews.

App Store Preview Videos

When I first started figuring out how to do these I was so close to throwing in the towel and skipping them. I’m glad I didn’t. Once I figured out how to have an easily re-playable sequence in both games and liked what was being shown, recording and editing in iMovie for 5 different devices was pretty quick (iPhone 5, iPhone 6, iPhone 6S+, iPad, iPad Pro).

I have much more appreciation for app developers who have a preview video. I also think you get a better idea of how the app feels with a video rather then just screenshots. Will they drive more downloads? I don’t know. But now I know how to make them so that’s another skill in the toolset.

Test Flight

Loved it. Would use it again. I should note that I haven’t tried any of the newer beta distribution platforms, but Test Flight did everything I needed it to do with very little friction.

AdMob

Monetizing an app with advertising is always a little controversial. I wrote these two games to teach myself Swift, get more experience with auto layout and multitasking as well as learning the latest version of iTunes Connect which I hadn’t touched in 2.5 years. I see them more as my playground to learn and use the latest and greatest Apple technology. I don’t think I’d learn as much if I didn’t release them. Having real users is critical in learning and understanding the entire Apple ecosystem. But I want my expectations from users to be realistic. I get to learn new fun things and they get to play them at the cost of a few ads. If I want to completely redesign an app to learn something new (which I did with Super Euchre) I don’t feel the same obligation to users that I would if I were charging them. That may seem cynical and an altruistic approach of completely free apps may be more palatable for a user but I did spend 4 months working on these games. Realistically I expect to make about $100/month pre-tax on these games. I’m already practically giving them away.

I am curious though if banner ads really do underperform against interstitial ads. Euchre has a banner add while Solitaire has an interstitial ad when starting a new game. It should be interesting to see which wins.

Overall

I hope people enjoy these games. These last few months have been a lot of fun creating them, getting them to testers and polishing them off. I’ve learned a ton!

Then WWDC happened.

Now to update both code bases to Swift 3.0…

Written by Nick Harris

June 23, 2016 at 6:59 am

Posted in Uncategorized

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.

Written by Nick Harris

June 7, 2016 at 5:41 am

Posted in Uncategorized

Core Animation

leave a comment »

Core Animation is by far my favorite framework to mess around with. Its been my favorite since I started writing Euchre way back for iPhoneOS 2.1. Its simple to use and can be incredibly powerful in calling attention to UI elements when they change. Its also very easy to over do it with animations. I liken it to salt and pepper in cooking. You can enhance your app with just a pinch but too much and it ruins everything else you’re trying to do.

I’ve been playing around with how to show trick winners and hand winners in Euchre for the umpteenth time over the last two evenings. Its one of the parts of continuously re-creating a Euchre game for iOS that I really love. This effort is especially meaningful after getting a grip on how to represent the game in AutoLayout.

I overdid my animations in Super Euchre (the version available in the App Store) particularly around when a team wins a trick or a hand. The state of the game was over represented on the view and the animations to those changes were jarring. With my new take on Euchre I cut those down substantially while still doing subtle things to draw attention:

 

I like it but I’d be interested in hearing thoughts*.

PS:
I had a blast with animations on Solitaire. Dragging piles was a little challenging but fun.

 

*I don’t present myself as a designer. I’m just a developer who wants to tinker with the design of my own apps that make little money.

Written by Nick Harris

May 11, 2016 at 5:31 am

Posted in Uncategorized

Top Toolbar Design

leave a comment »

I saw this screenshot from the Starbucks app tonight. I was curious (I’m not a Starbucks guy) so I downloaded the app myself.

Screen Shot 2016 05 05 at 10 29 57 PM

Personally I like the design a lot. But what really caught my eye is the use of a top of view toolbar instead of a bottom tab bar.

For my Solitaire experiment I decided to go with the same top toolbar approach. When I went back to working on Euchre I made the same decision.

Screen Shot 2016 05 05 at 10 30 23 PM     Screen Shot 2016 05 05 at 10 31 43 PM

The biggest reason for me was the perception of persistence that tab bar views have. Each tab feels like something that’s always active in the app. For my dumb card games, things like rules or best scores don’t need to feel like they persist. You can bring them up when you’re interested but can then dismiss them and feel like they’re “gone”. Using animations can enhance that feeling for the user instead of the flat feeling of switching between tabs. Presenting modal views on top of your base view feels more interactive to me then tabs.

I’ve also accidentally tapped another tab when holding my phone and jumping me from what I was trying to do. Having the navigation buttons further away from my “work area” means I need to make a more definitive action to switch my working context.

The Starbucks app seems to do exactly what I’ve been attempting to do with my horrible design skills. Views appear from the bottom and overlay the base view while leaving the menu visible. Swipe gestures can be used to dismiss them instead of reaching all the way for the top toolbar. Its not a difficult effect to do and I really like the feel of the app more then I would if they had used a tab bar. There are some things they could do to tighten down the animation (adjusting the background image after viewDidAppear is rather jarring) but all in all I do like this approach to app navigation.

Are there other apps taking this approach?

Written by Nick Harris

May 6, 2016 at 4:48 am

Posted in Uncategorized