Mutility 1.5.2

This version includes a ton of bug fixes and iOS 8 updates, including support for the new iPhone 6 and 6 Plus to really get the most out of the space available on those devices. There are no new features in this release.

I was never crazy about the sizes in 4 player mode, especially on the iPhone 4/4s, but I have to say it's quite spacious on the iPhone 6 and 6 Plus! The image above is from the 6 Plus - it's great to see that space used efficiently. 

Updates

  • Native support for iPhone 6 and 6 Plus
  • Built on iOS 8 SDK
  • Shuffled around and cleaned up some of the items in the settings screen.
  • Improved text size and layout of secondary counters

Bug Fixes

  • Tap state can no longer get stuck in a tapped (partially transparent) state

  • Player views in customization cells no longer re-rotate their layouts when scrolling from the bottom of the Settings table (discovered by Zev)

  • The status bar fades in/out nicely now, due to switching from a view controller based status bar appearance to a manual one via this Jared Sinclair article.

  • Background of transition animation container now matches the theme color (white theme had a black background before and looked like crap)

  • Game layouts were sometimes goofed up by the presence of the status bar, especially non-standard sized ones.

  • Replaced missing icon in the brightness selection cell in settings.

  • Toof’s layouts and wink trigger locations were goofed up on different sized devices and with/without the IAP view shown. FYI, Toof is an easter egg friend that you should find.

  • Baseline aligned the ‘Restore!’ button with it’s related text in Settings (Zev again). It was off by a fraction of a point and somehow this guy caught it.

  • Many more minor fixes and diddles

Development Notes

  • This release also laid the groundwork for localization into multiple languages.
  • I made a number of changes throughout to make scrolling through settings more performant
  • After the debacle of version 1.5.0, where a bug in my IAP code resulted in all features still being locked down after a purchase, I spent a lot of time refactoring. This was some of the oldest code in the app, and thus some of the poorest quality.
    • Expanded the IAP handler class to abstract everything from the other classes that use it. Previously, there were bits and pieces of IAP code here and there, now classes that need to know about the purchase just ask the IAP handler if the purchase has been made, how much it costs, and can request that the purchase be made. This is much simpler than what I had going on and removed some duplicate code.
    • A lot of duplicate work was going on, and that has been simplified away.
    • The bug that caused the 1.5.0 debacle was an attempt to prevent a crash that had occurred to a very limited number of users. The crash fix has been re-implemented now that Sam Marshall pointed out the stupid logic error I made.

As always, feedback is appreciated!

Mutility 1.5

It's been a long time coming, but secondary counters are finally here with version 1.5! What's a secondary counter you ask? It's a second, general purpose counter that's useful for tracking wins, poison counters, or for Commander/EDH. Enable them in Settings and pick the most relevant icon for what you want to keep track of. An intelligent default for 'Reset when game resets' is automatically picked for each icon.

  • Skull - Poison (come on, that one was easy)
  • Trophy - Win tracking
  • Crown - Commander/EDH
  • Medal - Commander/EDH or an alternate icon for win tracking

Secondary counters are easy to use - check them out in action.

Above, we've enabled Poison counters in a two player game. To increment or decrement the Poison counter, first tap to select it then tap elsewhere to increment / decrement as usual. In the example above, Kevin's poison counter is not selected, so tapping anywhere besides the counter increments or decrements his life total. Nate's poison counter is enabled, so tapping anywhere besides the counter increments or decrements the poison counter. Tap on the poison counter again to disable it and go back to life changes. Easy peasy. 

Just like life changes, counter changes are tracked and editable in the current game history.

If you don't have 'Reset when game resets' enabled for secondary counters, or just wish to manually reset them to 0, a counter reset button has been provided in the game bar.

The counter reset button to the far right only resets the counters, not the game. You'll also notice a new button here - the arrow encircling a die. This resets the game and rolls the dice in just one tap.

I'm quite happy with how the counters look and work. Great pains were taken to assure that they don't get in the way of tapping to increment/decrement. You'll notice that the layout is optimized according to the number of players and orientation. Here are some examples:

Because of the layout complications, only one counter per player is supported right now. There's no reason that layouts with more room (1 or 2 player games, for instance) couldn't support additional counters, so this may come in a future version. 

What else is new?

Secondary counters are the headline feature, but there were many small changes and bug fixes included in this release:

  • Bug fix: Occasionally, the timer would get 'stuck' and taps on the play/pause button were ignored. I believe this is straightened out now.
  • Bug fix: Tapping the status bar in Settings would not scroll to the top.
  • Added 'new game and roll dice' button and counter reset button in the game bar
  • Updated the buttons for History and to select the number of players with beautiful icons from the Symbolicons Block icon set. Counter icons are also from this set.
  • The Settings icon now spins when you tap it because it's awesome and this guy yelled at me for removing it a while ago. 
  • Added a fun easter egg to the Settings screen. See if you can find it ;)
  • Various UI improvements and polishing
  • Improved the look of the app icon with a mild color adjustment

Development Notes

I did some really important stuff behind the scenes this release. Special thanks to Zev Eisenberg and Sam Marshall for straightening me out in all sorts of ways.

  • Moved from a local git repo hosted on Dropbox to a remote repo hosted on GitHub and integrated with Xcode. 
    • I was getting progressively more and more in trouble with my previous version control system, as conflicted copies of my git repo (!!!) began to accumulate and cause wild and crazy issues. Big thanks to Zev for putting me on the correct path and to the Apple engineer responsible for Xcode's integrated version control that dug into my project and got me up and running after the conversion. WWDC tools lab FTW.
  • Spent some quality time refactoring my code for consistent style and conventions. This was inspired by Brent Simmon's various blog posts on the subject.

 

Mutility 1.4.0 - Beta 1

When I started on 1.4.0, the headline feature was supposed to be the addition of counters. However, so many other things came up while overhauling the interface code to support them that 1.4.0 will not include them. In fact, after nearly a month of work I still haven't settled on exactly how I'm going to implement them in the UI (although the database now supports them). More on that in a later post; let's talk about what's new in Beta 1, which I'm releasing tonight to beta testers.

Bug Fixes

  • Discovered by Tommy V: 3 player layout had issues when the status bar was visible.
  • Discovered by Tommy V: “In a few layouts, the plus side of the player’s background grows by a few pixels whenever you are subtracting life. It happens for any number of players for any layout that has the text rotated putting the baseline parallel with the side of the phone.
  • In some circumstances the timer could get stuck in a paused state, but show that it’s running. Although it could be reset, the pause button didn’t toggle when tapped.
  • With three players in certain orientations, the layout did not completely fill the screen.
  • Names and life totals are scaled to fit correctly when they get long, instead of being cut off.
  • Life totals shown in the player customization and orientation selection cells reverted back to their original values after a starting life change if you scrolled all the way to the bottom then back up.

User Facing Improvements

  • New option to change the life increment during a tap-and-hold (1 or 5)
  • Brought back two finger tap for lifelink /extort option in settings
    • Works with 2-player games only, off by default
    • Known issue with Beta 1: Sometimes during a two-finger tap, the player view will look like it's not being pressed anymore. Working on that.
    • Known issue with Beta 1: The game history does not show that a particular life transaction was lifelink, but the player life numbers it shows are correct
  • Resetting the current game does not reset the timer anymore by default
    • A new option to override this is included in settings
  • New dice section in settings
    • A note explaining that the dice results are actually random, since several people have commented that they don't trust app dice
    • An option to turn off tie skipping when performing a dice roll
  • New color option: Pink
  • Fun animations occur when customizing player colors and orientations
  • Life totals are centered vertically when player names are left blank
  • New custom animated transitions to settings & history screens
  • Unified look of history and settings navigation bars
    • Blue background with white content, iOS 7 style text, status bar always showing
  • Moved to toggle switches instead of text-heavy segmented controls in settings
  • Removed circle around +/- watermarks and made them slightly smaller in an effort to make them look less like buttons (folks are always trying to tap on them directly)
  • Numerous other little UI tweaks

Development Notes

Although there aren't many big new features in 1.4.0, the changes to the codebase were extreme. With each day that goes by I learn so much more about developing for this platform, and along with that comes a big pile of technical debt. I had to gut most of the interface code and rebuild it the right way (note: the right way is what I currently think is the right way, and I'm sure I'll be embarrassed about in just a few weeks as usual).

The most important change that I made was to unify the three separate classes I had built for displaying player views (the rounded rectangles all over that display a player's life/name/color, or represent that in an icon in settings or the history) into one, well constructed and reusable class. In doing so, I rebuilt it from scratch using Core Animation layers instead of UIViews, which gave me much more flexibility in controlling animations and the placement of UI elements. Getting this right is critical to how I implement counters, so it had to be done first.

What's Coming in the Next Beta?

  • Timer usability improvements
    • After a great discussion with @brandonadamb, it became clear that I didn't get the timer usage flow right (even though I thought about it quite a bit). I think we've figured it out, and that's the next thing to straighten out.
  • Update history table cells in preparation for counters and include lifelink

Alright, that's enough blogging. Now, back to work.

 

 

On Designing a Game Timer

"Add a timer, how hard could that be?!" you say.  

Seems easy enough, but introducing one to the UI in a way that doesn't suck isn't trivial, nor are all the easy to miss corner cases that need addressing. Adding this simple feature is easy, getting it right needs some thought. Let's take a wander through the thought process behind designing the new timer that shows up in Mutility 1.3. 

Where Does It go?

I looked at all sorts of places to put this thing:

  • One in each player panel
    • Pros: Each player always has a timer oriented towards them for readability
    • Cons: Clutters the clean player panels. Up to four numbers ticking away all the time is distracting and sort of redundant.
  • In the main button bar, toggled on by a switch in Settings
    • Pros: It's a secondary feature, so would be hidden until the user decides to turn it on, keeping the clutter down for everyone else (Doesn't take up any space on the main bar when not in use). Adds value to the in-app purchase by making it a paid part of the customizations. 
    • Cons: Trying to cram it into the main bar with the rest of the icons is a big mess. Putting it on a secondary button bar would be another step after the user has toggled the timer on. No way to do this simply and cleanly.
  • In a secondary button bar, toggled by a button in the main button bar
    • Pros: Giving the button prime real estate makes it simplest to use and can use the existing sliding bar mechanics to toggle it back and forth. 
    • Cons: An icon from the main bar has to be removed to make room for the timer toggle button, making that feature less obvious to the user.

I looked at all of these options, partially implementing and testing each way. The best implementation turns out to be the third way, even though it requires banishing a button from the main bar - the dice roll button. No other button could be moved, since they either bring up modal views or slide in a bar. The dice roll button has been moved to the game bar (the one you get when tapping the new game button), which makes sense since a dice roll typically happens at the beginning of a game. UI figured out, BOOM, moving on to the hard stuff....

What are the gotchas?

When figuring out how to implement a game timer, you come up with all sorts of questions (and hopefully answers). Here's my internal Q&A session:

  • Should it start automatically when a game is reset? 
    • No. When resetting the game, you may not immediately start again, or even want a timer. Firing up the timer should always be done manually to avoid unwanted behavior. 
  • What dedicated controls does it need?
    • Pause and reset. You need a dedicated timer reset so the whole game doesn't have to be reset simultaneously. Resetting the timer and resetting the game are not always coupled.
  • What happens when you switch games? (2 player to 4 player, for example)
    • Pause the timer. Switching to another game probably means that the user isn't involved in the previous one any more, so it doesn't make sense to keep the timer running.
  • What happens when you switch to another app?
    • Keep the timer running. Remember, we're running on a smartphone. Over the course of game you can expect the average user to leave the app to deal with messages, answer phone calls, send x-rated Snapchats, etc. If they had to un-pause the timer every time they came back into the app, it would be a huge pain in the ass and they'd stop using the feature.
  • What happens when the timer is running, the user switches to another app, and iOS kills Mutility to free up memory?
    • iOS is very aggressive about closing backgrounded apps when there's memory pressure. The way the timer is implemented must be robust enough to handle the app being killed. When the user re-opens the app, they don't know that it's been killed, and nor should they. It's on me to make it look like it was running the whole time.
    • When the app enters a backgrounded state (i.e. you switched apps), I stop the timer and record the time I did so. When the app enters the foreground again (i.e. you switched back to it, or it was killed and was reopened), it looks to see if the timer was supposed to be on then computes what the elapsed time should have been. By just assuming it's going to be killed, all the guess work is removed, and it appears to the user that the timer has been going the whole time.

How can you make it more fun and intuitive?

I spent a real lot of time working on the icons for this feature and went through various incarnations of what a stopwatch icon should look like. The icons should be instantly recognizable as being related to a timer, fit with the style of the existing icon set, and include little details that can help give context to what's going on. I'm very happy with how delightful the little details worked out to be:

  • When the timer is running, the stopwatch hand on the main button bar animates ticks in sync with the elapsed time. The animation is subtle, but you can tell at a glance if the timer is running even if the timer bar isn't visible.
  • The position of the stopwatch icon's start/stop button is down when running, up when stopped.

So that's it. I'm nearly done with 1.3 that includes this feature - should hit App Review in the next couple days and be in the store sometime next week.

Mutility 1.2.1

This minor update adds two more colors (orange and purple, in line with the iOS 7 color palette) to choose from in scroll view, a button to reset the app back to its defaults, and a number of UI updates to the settings and history screens. I've also updated the in-app purchase to be more clear - once paid for you get all the features and any future features. It truly unlocks everything, and I wanted that to be obvious.

I spent most of the development time working on installing a basement underneath the tables, so let's have a chat about it.

Installing a Basement

It's not very accurate to call iOS 7 flat; although it has removed the gloss and texture of previous versions, it is still very much three dimensional. The third dimension isn't one that is jumping out at you, instead it's the presence of layers. You'll notice this all over the OS - panels are sliding over each other all over the place, and in many cases perform a wonderfully saturated blur of the contents underneath to help keep the layering metaphor obvious.

The concept of having a 'basement' in a UI is not new, but it fits iOS 7 designs very well. You can think of the basement as the lowest layer of a screen made of up a pile of overlapping layers. For this layer I used a dark gray, similar to color of the linen in iOS 6 and below that was used system wide as sort of a basement texture. On top of this goes the table and on top of those table cells go the table section heading cells. I made the table section heading cells partially transparent to enhance the layering effect. Take a gander at this portion of the settings screen from 1.2.1 to see what I'm talking about.

 You'll also notice that I ran out of room for colors, so now you scroll through the list.

You'll also notice that I ran out of room for colors, so now you scroll through the list.

The in-app purchase view lives in the basement now, and the table has been shifted down to expose it (when the purchase is made, the table shifts to cover it up). The basement also shows up when you scroll to the end of the table, exposed during the bounce. You can barely see through the section header cells to the table cells below, just enough to make the layering noticeable. The history table is set up in the same way.

I think that being true to this UI metaphor makes for a really nice, subtle, and useful effect and I'm very pleased with how this turned out.

 

Mutility 1.2.0

Mutility 1.2.0 makes its move into multiplayer MTG games by adding support for 1, 2, 3, and 4 players. Best of all, selecting the number of players is a free feature. To accommodate this, there are settings and history table updates, as well a new pair of buttons on the main screen. All in all I think it came out pretty good. Touch targets are still big enough even with 4 players on the iPhone 4/4S. On to the full list of changes:

  • Added support for 1-4 players (a big undertaking)
    • Each number of players has 4 orientations to select from
  • Dice roll moved to main screen and does not restart the game
  • Removed lifelink/extort feature (two-finger tap) since it was too unreliable to keep
  • Various UI tweaks
  • Known issue: Upgrading from previous versions blows out the database, resetting everything to defaults. Due to my incompetence, I couldn't figure out what was going on. In my defense, typing in your names again shouldn't be too hard.

1-4 Players: A big undertaking.

Although it seems like adding support for 1-4 players wouldn't be a big deal, it was a massive undertaking. The database underwent significant changes, the history table cells had to be completely redesigned, dynamic icons were designed to show the various orientations of the player life panels, and much, much more. Here are some of the highlights that I'm particularly happy with:

  • In the settings screen a Symbolicon (pencil / paintbrush / marker) is now shown in the customization cells for 1 or 2 player setups. For 3 or 4 players, these icons are replaced by an icon of where on the screen the particular player panel resides. This is helpful for figuring out which player you're customizing. They also animate changes in orientation, which is freaking awesome.
  • The above update now makes the settings screen have a consistent set of icons straight down the left edge - very classy.
  • When you request a dice roll, the dice are scaled in size relative to the player panel size and are tossed from wherever the 'bottom' of the panel is oriented. It's like it's being thrown from each player wherever they happen to be.
  • The history table now shows the life change for a particular player, as well as that player's location on the screen. Removing the lifelink feature made this cell much cleaner, since life transactions only happen to one player at a time.
  • While the app loads, a white screen can appear briefly between the splash screen disappearing and the main screen appearing. This is mostly fixed for iPhone 5S, but older phones may still show this nonsense since they're slower.

Mutility 1.1.1

I really wish I had a transcription of a recent episode of the Accidental Tech Podcast , because Marco had an excellent quote that sums up what this release is all about - something to the effect of "All these little quality decisions really add up". This is a release that's almost exclusively about polishing and being fussy about getting everything pixel perfect. I'm really striving to make Mutility as beautiful, clean, and functional as possible, and I think i've made some strides in this release, even if they're mostly in the settings screen this time around. Here are the main updates:

  • Reworked and organized the Settings screen, adding a number of icons from the beautiful new Symbolicons Air icon set. Adjusted fonts, colors, and borders to be more in line with the standard iOS table format.
  • Fixed a number of layout and animation bugs and spent way too much time assuring things are laid out pixel perfect. 
  • Added the player names to the preview in the customization cell in the Settings screen. They update in real time and rotate with the selected orientation. Giggedy.
  • Fixed the jarring abrupt appearance of the UI when the app first opens
  • Although I like the look of an all-lowercase name for Mutility, it looks awkward in many places. From this release on, Mutility is now a proper, proper noun.

And good news from 1.1.0 - there are more active users than ever and there have been no more crashes! It still may be too early to call it, but I think I finally straightened it out.

 

Symbolicons Air

Jory Raphael of Symbolicons fame recently released this beautiful set of iOS 7 styled icons, and it was the perfect answer to cleaning up and organizing the Settings screen. I first heard about Jory's work from Dan Benjamin of 5by5, where he did all (most?) of the podcast artwork. This icon set is great and a steal at $29, considering the licensing agreement allows for royalty free usage in commercial products like this.

You can buy the Symbolicons Air set here. The licensing agreement is very simple and fair. 

 

Tapstream Analytics Updates

This version includes an updated version of the Tapstream SDK, 2.5.1. I now collect the device's Advertising Identifier to more accurately judge usage. Originally, I did not collect this to be sent to Tapstream because I didn't understand the privacy implications. Turns out there really are no privacy implications, since it's an anonymized number that Apple has designed specifically for advertisers. If the user has 'Limit advertising tracking' enabled, the following rules apply with regards to using this identifier:

If the user has limited ad tracking, use the advertising identifier only for the following purposes: frequency capping, conversion events, estimating the number of unique users, security and fraud detection, and debugging.

Tapstream will use this identifier exclusively for conversion events (in-app purchase logging) and estimating the number of unique users. Using this unique ID is particularly important for estimating the number of unique active users, and I'm very interested in keeping up to date on that.

You can sign up for Tapstream for your app here and help me out at the same time!

Mutility 1.1.0

This is the first update with user-facing improvements (compared to me just cleaning up my own mess on the back-end)! Overall, the look has been simplified. Mutility 1.1.0 nixes the center black bar and the white background behind the life panels in favor of a simpler, theme-able look. Selecting between the white and black themes is included with the app for free, and makes a big difference in the looks department depending on which color iPhone you're using. The center bar animations have improved and the life panels have grown slightly. Further, the subtle triangles denoting which side to tap for increasing/decreasing life have been replaced with easier to see and unambiguous +/- symbols. But wait, there's more:

  • Updated UI - as described above. The center bar animation is much more fun now.
  • Crash fix - Opening and closing the settings or history screens quickly with a poor network connection could cause a crash in some cases. Been trying to squash this one in the past two versions and think I finally nailed it. More on that later.
  • Embarrassing bug fix - Users who had not purchased the customization & history in-app purchases were shown the wrong life totals in the history table. Yikes, fixed.
  • Integrated Tapstream analytics

Example of the white theme with a dice roll. Check it out on a white iPhone.

And now on to the TL;DR part:

 

Crash Fix - Take 2

Finally, I think I've gotten to the bottom of the crash that can occur when opening and closing the settings screen with a spotty network connection. I've received two Crashlytics error reports about this, had it happen to me once out and about and then just recently during testing and (thankfully) in the debug environment. Although the bugs I squashed in 1.0.2 could also cause crashes, this was probably not what was happening. It was this Stack Overflow thread that finally pointed me in the right direction.

The only pieces of code I didn't write from scratch in this app were the in-app purchase methods I built up from Ray Wenderlich's excellent tutorial. The line that was crashing was always a completion handler assignment, like this:

_completionHandler(YES, skProducts);

Each time the settings or history screen is opened, I ask the App Store for the current price of the in-app purchase. If you have a poor network connection, the App Store may not have responded by the time you dismiss the screen. My original thought was that that the method being called, either request:didFailWithError: or productsRequest:didReceiveResponse:, was failing because the object that the completion handler was to be delivered to (either my Settings screen or the History screen) had been dismissed and thus deallocated. The fix in 1.0.2 was to properly un-register these objects as observers from NSNotificationCenter when they were dismissed, so the product request response wouldn't get sent to a deallocated object and crash.

But I was mis-reading the error. The error pointed the specific line in these methods where _completionHandler was being set. Here's one method that had crashed, which was directly from Ray's tutorial:

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
NSLog(@"Failed to load list of products.");
_productsRequest = nil;

_completionHandler(NO, nil);
_completionHandler = nil;
}

The SO thread pointed out that after _completionHandler is set, it's nil-ed out, and that a second call to it would cause a crash since it had been deallocated. Since I make a request each time one of these screens is opened, it is quite possible to make multiple unfulfilled requests by opening and closing the screen with a spotty network connection. Once that network connection gets its act together, multiple store requests could then come back. The first would be OK, but subsequent ones would cause a crash. I took the advice of that thread and added logic to tell if a request had been placed already and assured that I wouldn't place any more. Pfew.

 

Embarrassing Bug Fix in the History Screen

This is what I get for rarely testing the app without the in-app purchase, well, purchased. If you had not purchased 'The Basics', you are only shown the last life transaction in the history table and told how many more you're missing out on. Well, I was showing the correct life delta, but the life totals were stuck at whatever the first transaction set it to. If player 1 lost 2 life at the beginning of the game, this cell would report that they had 18 life permanently. Oops, fixed, eek.

 

Tapstream Analytics Integration

Like Crashlytics, Tapstream was another service I discovered on Marco.org. So what am I using this for? 

  • Real-ish-time install and app opening statistics
  • Monitoring the effectiveness of the links I embed in the app and on social media
  • That's it

They let you collect all sorts of information, but I've opted out of all of it. The analytics I collect don't even use the Advertiser ID. It's completely anonymous and I don't gather any information about your phone. 

Mutility 1.0.2

This thing above is the invitation to integrate Crashlytics into mutility. After the terror of having a crash in 1.0.0 with no way to see what's going on, it was clearly time to get some insight into future problems (that will never happen, right?). Crashlytics is a sponsor of marco.org, which is where I first heard about them, and before this version even hit App Store review, it saved my butt. But first, here's what's new:

  • Fixed bug where intermittent network activity could cause a crash when leaving the Settings or History screens
  • Changed history table segue to modal and the animation to a flip – works much better with my mental model of how it should work (history lives on the back, not off to the side)
  • Integrated Crashlytics
  • Improved dice rolling randomness
  • Added a 'Leave a Review' button in Settings
  • Various back-end clean-up and optimizations

Crashlytics & Its Big Find

While playing with the 1.0.2 beta and quickly flipping back and forth between the settings screen and the main screen, it suddenly crashed. I was in an area of very poor cell reception, and had noticed that it couldn't fetch the in app purchase price from the store. The app re-launched no problem (something that would NOT have happened in 1.0.0), and shortly thereafter I got an email from Crashlytics. It had crashed in the request:didfailwitherror: method in the in app purchase handling class with 

Exception Type: EXC_BAD_ACCESS

Code : KERN_INVALID_ADDRESS at 0xc

A quick Google search found that this is an error typical of sending messages to deallocated objects. Well, the request:didfailwitherror: method sends a completion block to the Settings and History view controllers. After about a half hour of digging around, I discovered that I was not properly unregistering these view controllers from Notification Center (I was unregistering in viewdidunload, which is deprecated, womp). In spotty cell reception, sometimes you've already dismissed the Settings or History screen before the in app purchase price is loaded from the store. If you don't unregister that guy as an observer, a notification will get sent into the bit bucket and you'll have a crash.

This issue was fixed (geeze, I hope) by unregistering the Settings and History view controllers as notification observers in viewwilldissappear:animated.

Mutility 1.0.1

This is a bug fix version (with very minor other updates) targeted at fixing a rare crash and a more serious crash. Read on for the dirty laundry.

Update Overview

Status: Submitted 5/28/11 and waiting for review.

  • Fixed: History table editing crash
  • Fixed: Database integrity
  • Very minor UI tweaks and some new messages during in-app purchasing

Fixed: History Table Editing Crash

Problem: When a user swipes a cell in the history table to delete it, but instead dismisses the history table, the app would crash after a slight delay. This one didn't come up in beta testing, and just goes to show the weird edge cases you need to somehow predict as a developer.

Fix: This SO thread tipped me off that methods can still be called on the table after it's been dismissed, in particular one relating to the editing state of the cells. By forcing the editing state to be off before the table disappears, these methods will no longer be called. 

Fixed: Database Integrity 

What: Should the app get killed or experience an issue when the initial database is created the first time the app is downloaded (or perhaps even during an update), the database could be corrupted in such a way that the app crashes almost immediately after opening. The user would have to delete the app and reinstall to stop this crashing nonsense. My apologies to @MattMarks_ for being the unlucky one to experience this.

Fix: This issue was 100% caused by my inexperience with Core Data. The database back-end of this app is built on Core Data via a UIManagedDocument. This is how I achieve persistence of user settings, life transactions, etc.  There were several instances where I was not handling database errors at all (aside from a comment to the tune of //NEED TO HANDLE THIS), and I wasn't doing enough checks to see if something had gone wrong. Now, the database is checked and rebuilt if there is an issue. More work needs to be done on this to assure preservation of existing data (instead of wholesale wiping the thing out and starting fresh), but I need to get smarter in this area first.

Mutility 1.0.0 - Submitted For Review

It's been a long, sometimes difficult journey, but I'm happy to say that I've submitted the very first version of my very first iOS app to the App Store for review. I'm also happy to say that I'm quite proud of how it turned out and that it will truly be the best life counter in the App store.

I submitted it this morning, and according to Shiny Development, the average app store review time is 6 days. Now, I'm fully expecting for mutility to get rejected at least once, mainly because I've been told to expect to get rejected at least once. There is a nearly infinite number of reasons an app can get rejected due to extensive gray areas built right into Apple's App Store Review Guidelines. Nothing more to do than wait and see.

In the mean time I've completed mutility's home page (which is where mutilityapp.com redirects to), set up a twitter account and support email address for it, and have begun collecting my thoughts for a series of posts about it from my perspective as a new iOS developer.

mutility 1.0 is now in beta

If you haven't figured this out already, mutility is the name of the iOS 7 app I'm developing. It's a premium life counter for Magic: The Gathering., and it's the first iOS app I've ever developed.

On 10/19/13, I released mutility 0.0.0 to all one of my beta testers. Today I released mutility beta 0.0.4 to my beta testers, who have ballooned to a group of four. Feedback has begun to come in, and I couldn't be more excited to get this thing out the door and into the App Store!

With the 0.0.4 build, I consider it feature complete for the initial 1.0 release to the store. All user-facing features (read: fun to implement) have been added, so all that's left is boring back-end stuff like setting up the in-app purchases and making sure I got the database implementation right. Who am I kidding though, I'm also going to obsessively tinker with the graphics until it's just right.

I'll have more to say once I get closer to releasing this thing. Stay tuned. 

If you're interested in beta testing the app, drop me a line.