Paint Code Slider

I saw the Humble Bundle today for $19.99 and in it was PaintCode! Definite must buy if it’s still available when you’re reading this.

I tried PaintCode a few months ago but never investigated what it could do. When I last looked the tutorials were unhelpful. All they showed is how to produce a static image onto the iPhone screen with no interaction.

I’ve been looking in to making more dynamic and intractable UI elements using Paint Code. At the same time I thought I’d start a series of tutorials creating different simple UI elements each time.

So, my first on is a slider implementation. I’ve tried to make it as like the iOS UISlider as possible for no particular reason other than the iOS one seems to work pretty well.

Anyway, here’s a quick video of what I created…

You can get the repository here… Paint Code Slider

I’ll eventually be making a screencast of how I made it but I haven’t yet. Come back in a few days and I may have it made.

Anyway, thanks for reading.

Animate with springs!

Today I was having a look at some of the different UIView animation block methods and I noticed one that I’d never seen before. I read the docs and it is an amazing little function added for iOS 7.

The function (which is a bit of a mouthful as usual) is…

[UIView animateWithDuration:(CGFloat)duration
                      delay:(CGFloat)delay
     usingSpringWithDamping:(CGFloat)damping
      initialSpringVelocity:(CGFloat)velocity
                    options:(UIviewAnimationOptions)options
                 animations:^() (animations)
                 completion:^(BOOL finished) (completion)]

Like I said, it’s a bit if a mouthful.

I haven’t fully explored what is possible with this yet but from my first couple if attempts I was able to get some very effective UI animations that would have taken a lot of messing around using the standard block animations.

The two new parameters are fairly self explanatory but just to be certain…

usingSpringWithDamping
This is a float between 0 and 1. It affects how “strong” the spring is. A value of 1 will not oscillate at all. It will slow down until reaching the target value. A value of 0 is the opposite, the spring will oscillate infinitely. Now, I’m not sure how this works given the time constraint but I’ll have a mess around in a bit.

initialSpringVelocity
This is also a float and is a relative value. The actual velocity unit is “total distance of the animation per second”. I.e. If your animation has a total change of 100 points then a value of 1 will set the initial velocity at 100 points per second in the direction of the animation.
This last bit is quite important. The polarity of the velocity is not up or down but it is relative to the direction of the animation change. If you give it a negative number then your animation will start by “popping” in the opposite direction before springing back.

A quick note
I talk about “direction” in this blog but again that’s not to say that this can only be used to animate changes in position. The spring essentially maps to a custom animation curve. This can be used for rotation, scale, transformation, anything that a standard animation can be used for.

Have fun messing around with it.

A quick video of something I made using the animate with springs API.

Why I wish I’d never used Magical Record

The first time I used Core Data I thought it was amazing. However, I got it all very wrong. I had “helper” functions in the App Delegate, I didn’t use any relationships in the data model, etc… All very wrong.

Then I learned more about it and did it all myself again, this time it was excellent! I understood how the relationships worked, I was using NSFetchedResultsController. Merging changes from background contexts, syncing changes up to a server, everything.

Then I found Magical Record… this is awesome! (I thought).
It makes everything to do with Core Data so easy! (I thought).

It puts hundreds of different functions in to one line of code. Creating fetches becomes so easy, saving is easy, NSFetchedResultsController creation is now one line of code.

I went to town. Completely integrated it into my app.

Then I migrated my app from Xcode 4 to Xcode 5.

Ran the app… everything is fine! Woop!

Wait… the UI isn’t responding, I can’t press any buttons, no exceptions thrown either, what’s going on?!

I paused the app and the first line in the stack trace looked a bit odd.

magicalrecord

Looks like something to do with Core Data is blocking the main thread. Time to put my debug hat on…

Right, CoreData, where could the error be?

Wait… I have no idea. Something in Magical Record is doing something that looks like it’s causing a deadlock between threads.

Do I know where it is? Nope, I didn’t write it.
Do I know where to start looking? Nope, this code is alien to me.
Do I wish I could pull Magical record out of the project? Absolutely.

Is this blog really just a rant?

OK, let me get to my point.

I doubt that Magical Record is fully to blame for this. I’m guessing that somewhere I used it in the wrong way that caused this error. I guess…

But that’s just it. I can only guess at what is wrong.

Because I’ve relied so much on someone else’s code there isn’t really anything I can do to work out how to fix it. I don’t know the inner workings of my app when the inner workings is what I’m building.

I’ve since started a couple of other projects using CoreData and networking and neither of them use AFNetworking or Magical Record. Not because I think they are bad or don’t work, but because I know that I can do everything I need just as easily and just as well. In fact, in both cases, my own code worked better for what it needed to do than either of these frameworks could do for me.

Of course, I’m not suggesting that everyone should stop using Magical Record and AFNetworking. Just make sure you know how and why they work before diving in head first. There will come a time when you need to know why something is acting in a particular way and you’ll need to know the fundamentals.

I’m stuck with two options at the moment.

1. Try and work out what is happening that is causing this deadlock. I have no idea if it’s my code or Magical Record code.
2. Try and remove Magical Record completely from my app. This is no mean feat. There are uses of it all over the place.

::Sigh:: back to work :(

NSCalendar isDate:equalToDate:toUnitGranularity:

During the beta releases of iOS 7 there were several mentions of a couple of new functions on NSCalendar.

- (BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)granularity;
- (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)granularity;

When I first saw these it was awesome. It makes comparing dates a hell of a lot easier and puts a lot of maths in to one line of code.

The usage is along the lines of…

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

BOOL datesAreEqual = [calendar isDate:firstDate equalToDate:secondDate toUnitGranularity:NSDayCalendarUnit];

datesAreEqual would then be YES for dates on the same day. Not necessarily the same hour, minute or second, etc…

HOWEVER

When the GM of iOS 7 went live, Apple seemingly removed these functions. ::sad face::

Anyway, I’ve implemented my own version which works in pretty much exactly the same way.

It’s a category on NSCalendar.

The header just has the functions.

#import <Foundation/Foundation.h>

@interface NSCalendar (equalWithGranularity)

- (BOOL)ojf_isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 withGranularity:(NSCalendarUnit)granularity;
- (NSComparisonResult)ojf_compareDate:(NSDate *)date1 toDate:(NSDate *)date2 withGranularity:(NSCalendarUnit)granularity;

@end

You can get it on GitHub.

It will also be available shortly through CocoaPods.

Feel free to add it in to your projects.

The Hamburger Menu – is it a good thing?

I’ve always been doubtful about the “Hamburger menu” in iOS apps.

For those who don’t know what I’m talking about it is this style of side menu used more and more in apps recently…

Facebook Hamburger Menu

Facebook hamburger menu.

It gets its name from the icon on the button used to open and close it that looks like a hamburger.

The more I see it the more I think it’s just a dumping ground for miscellaneous items in apps.

It’s a place that designers go to when they don’t know where to put stuff in the app.

Take a look at any Apple app. None of them uses a Hamburger Menu.

For a few other examples of great apps with not a single Hamburger Menu in sight take a look at these…

If something doesn’t deserve to have pride of place in your app then it shouldn’t be there at all. Don’t just stuff it into a hamburger menu.

There was a quote from WWDC 2013 about “Designing great apps”. The guy said something like…

Find out what the primary function of your app is. Then list the secondary functions and the tertiary functions.

Make the primary function visible as soon as the app starts up. Make it look nice and make it engaging.

Put the secondary functions only a few taps away but don’t make them detract from the primary function.

For the tertiary functions try to find a way to write them out of the app. Are they absolutely necessary?

I agree with this 100%. In my view the hamburger menu is a placeholder for these tertiary functions. It shouldn’t exist. Apple didn’t create it. Apple doesn’t use it. Why should we?

A couple of “firsts”

I’ve recently done a few things in my app development that I’ve never used before. I’ve done things in a similar way but I’ve never been satisfied with the resulting code. The apps worked but the code either wasn’t elegant or tidy or I felt like I’d bodged it.

Anyway, I thought I’d share them just in case you feel the same about your code.

Auto Layout constraints in Interface Builder

After reading Ray Wenderlich’s book iOS 6 by tutorials especially the Auto Layout chapters I decided to upgrade my current app to use Interface Builder auto layout constraints.

My usual practise is to use IB to throw the UI elements on the screen and then code the constraints myself. I always felt like it was a bit messy. I had an interface that didn’t look like the app and code that seemingly did half a job.

Anyway, I followed all the rules from the excellent tutorials in the book and everything worked like a dream! I was animating, constraining and truncating like a demon! The end result was a massively reduced code base and a better looking interface file and everything worked perfectly.

UIPageViewController

Again, I’ve used this before but not for a very long time. The last time I used it was in the early days of my iOS dev and it was a complete mess.

I added a UIPageViewController subclass to my storyboard and with very little code got it to work. Taking a previously single view controller and converting it to a navigator with swipe gestures and spaces between each page.

Another really pleasing outcome from this with not too much effort.

This lead on to the next first…

NSObject IBOutlets

When configuring the UIPageViewController above I had to give it a datasource property. Much like a UITableView or UICollectionView it relies on this datasource object to tell it what to display on the screen.

Usually I would just make it the datasource of its self. However I’ve now started trying to practise clean coding and wanted to create a specific class to do the job.

I created the NSObject subclass and added a property to the UIPageViewController. However, with my new “get things working in IB” frame of mind I decided to use the NSObject outlet available in IB. I added the object, set the subclass, connected it to the property and finally set it as the datasource all from within IB.

Again, it worked perfectly first time. I’ve been wanting to use this for a while but never had the opportunity or the time (or knowledge) to fully understand how it works.

I will definitely be using this more in the future. I can see myself subscribing to Graham Lee’s idea of creating separate datasource and delegate for table views and collection views.

I know from past experiments that OS X dev uses this principle quite a bit too. Who knows, maybe my next app will be a Mac app?

Interface Builder Y U no like auto layout?!

OK, a simple idea in auto layout terms…

I have a view, it has several buttons on it.

All buttons will have equal widths.
All buttons will have default spacing (between adjacent buttons and the superview).

Width of buttons therefore specified by width of super view.

In code it would go something like this…

// make all button widths equal
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:button2
                                                      attribute:NSLayoutAttributeWidth
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:button1
                                                      attribute:NSLayoutAttributeWidth
                                                     multiplier:1.0
                                                       constant:0.0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:button3
                                                      attribute:NSLayoutAttributeWidth
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:button1
                                                      attribute:NSLayoutAttributeWidth
                                                     multiplier:1.0
                                                       constant:0.0]];

// set spacing between buttons and subview to default
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[button1]-[button2]-[button3]-|"
                                                                  options:NSLayoutFormatAlignAllCenterY
                                                                  metrics:nil
                                                                    views:NSDictionaryOfVariableBindings(button1, button2, button3)]];

This is not ambiguous along the horizontal and has no conflicts at all. i.e. it’s a perfectly acceptable auto-layout setup. Obviously it would also need vertical layout but I’m not talking about them at the moment.

So, setting this up in interface builder…

I started out by making all the buttons width 20 (not as a user constraint, just a system constraint).
I then added “widths equally” between button1-button2 and button1-button3.
I then added the spacing constraints to this point… @”|-[button1]-[button2]-[button3]“.

This all worked fine. I was almost there. I added the final spacing constraint which was button3 trailing edge to superview. It added the constraint with the current value which happened to be 14.

This was all fine.

However, I found it had added a user constraint to the width of button1.

I deleted this which is fine.

I then selected the superview constraint I just added to button3 and ticked the “standard” check box. Now, what should happen is all the buttons should resize (slightly smaller widths) to accommodate the new constraint. Instead the constraint just deleted itself and I’m left in the same situation… WTF!?

If I can do this in code so easily why is it not even possible at all to do it in Interface Builder?

If anyone wants to try this I’m actually using 6 buttons in my project and they are spaced on a view of width 320.

Let me know if you get any further than I did…

An Auto Layout Experiment

I’ve only used Auto Layout very briefly in the past and not used it to do anything more than layout a static view (which seems kind of pointless) so I decided to get my hands dirty and do something with Auto Layout that I haven’t seen done before.

After a couple of hours I had a brief sample of a Bejewelled style game together all using Auto Layout!

Here’s a quick screencast of me playing the game…

It was improved slightly after recording this.

All of the animation was done using auto layout constants. It was hard work getting my head around deleting and adding constants and I think it would be fairly simple to improve the animation for instance when a column of three blocks is deleted or when a brick falls into a row/column that then gets removed as a result of it landing.

Anyway, you can see the code on Github. It isn’t documented, it isn’t tidy and it wasn’t meant for production, I just made it as a learning exercise. But if you can learn anything from the code then all the better for it.

If you have any questions about the code then let me know in the comments and I’ll respond ASAP.

Update

I’ve now pushed the latest changes of the code on to Github so you can get a more complete version of the game.

OJFSegmentedProgressView

I’ve always been good at creating “parts” of apps but I have trouble completing the rest of the app to go around it.

So I decided to create an open-source iOS control and make it available through CocoaPods.

The control is a segmented progress view, it displays progress between 0.0 and 1.0 in segments. It is a control I created for a full app but it was never used. I also didn’t add much flexibility to it originally.

I started from scratch over the weekend. My goal was to provide as many of the functions available with UIProgressView as possible to make it as easy to swap out and learn as possible.

The result is OJFSegmentedProgressView.

Using the control is simple. Install it using CocoaPods and set the view up with code like the following…

- (void)viewDidLoad
{
    [super viewDidLoad];

    OJFSegmentedProgressView *progressView = [[OJFSegmentedProgressView alloc] initWithNumberOfSegments:13];
    [progressView setFrame:CGRectMake(20, 100, 280, 20)];
    [progressView setTrackTintColor:[UIColor lightGreyColor]];
    [progressView setProgressTintColor:[UIColor darkGreyColor]];
    [progressView setStyle:OJFSegmentedProgressViewStyleContinuous];
    [self.view addSubView:progressView];
}

The control also works if added to a view in InterfaceBuilder (add a UIView and change the subclass).

Here is a quick video of the control in action…

One of the best things I’ve discovered about creating and sharing controls like this is the feeling of achievement you get when you see other people exploring and using your control. It’s still too early to celebrate any great successes but a couple of people have “starred” my github repo and it really made me feel good to be able to contribute.

The invisibility of good UX

In the beginning I only had Netflix. I used it as the predominant way of accessing movies and TV series. I never had a complaint other than it seemed to be lacking in its listing of shows.

After a few months I decided to sign up to LoveFilm instant also.

As a developer of iOS apps I like to think that I know the difference between good and bad UX and I would like to think that my apps all create a pleasant experience for the people who use and pay for them.

It was only when I signed up for LoveFilm instant that I truly realised how, firstly, good UX is completely invisible and, secondly, bad UX can summon wrath from even the most tech-savvy users on a level I didn’t know was possible from a piece of software.

To put substance behind my claims I thought I’d provide a comparison between Netflix and LoveFilm that I experienced recently.

Netflix
One of my favourite TV shows of all time is Mythbusters and recently Netflix has added another few seasons onto its library of shows. Brilliant!

I turned on Netflix and found Mythbusters (in the “recommended for Oliver” section) and started watching. When the episode finished the next episode automatically starts after a short countdown, excellent. (This stops after a few episodes so that it does not play endlessly incase you fall asleep etc…)

Then life got in the way and I had chores to do and places to go so I got up, turned off my TV and XBox and went about living life.

Upon returning to the sofa I wanted to carry on watching Mythbusters. However, I had no idea which episode I was watching or which season.

When I turned on Netflix, the default starting point in the menu is “Recently Watched” and the default show in the currently selected position is your most recently watched show.

I pressed “A” on my Xbox controller and the episode I had stopped watching started playing again from the exact place I left it at! Brilliant!

LoveFilm
Another of my favourite TV shows is Battlestar Galactica and this is only available on LoveFilm instant.

I turned on LoveFilm and couldn’t find an easy way to get to Battlestar Galactica so I had to search. No problem there… Click “Search by Title” and enter “B A T T L…” Battlestar Galactica pops up underneath the search. Oddly it is split up into four separate and unrelated seasons.

Anyway, I started watching. An episode finished and I was thrown back to the menu showing only episode one. There was no opportunity to go to the next episode. OK, so I browsed to the next episode and selected it to start playing.

Then I had to leave and turn off the XBox.

Upon returning to LoveFilm there was no sign of me ever having watched Battlestar Galactica before. It seems odd that I could remember what the XBox was doing but the XBox itself could not?! Surely it can’t be that hard to add a simple “Recently Watched” menu?

So, I went into the search menu. I was hit with the same situation, no record of ever having searched for anything before. My only option was to start searching again from scratch. So I did… “B A T T L…” Battlestar Galactica popped up (again split into different seasons).

A selected season one and found the list of episodes… all 24 of them… with nothing to tell me which ones I had watched, which ones I hadn’t, where I was up to, etc…

I selected an episode, watched 5 minutes and then realised I’d seen it before so went to the next episode and repeated this process until I found where I was up to.

This happened every time I wanted to carry on watching the show!

Summary
The difference is amazing.

On Netflix a single button press is enough to carry on watching from where I left off.
On LoveFile it requires something like 40-50 button presses and 5-10 minutes of watching and re-watching to achieve the same thing.

It’s only through experiencing a truly bad UX that I realised that a good UX is completely invisible to the user.

Things that you interact with to access services, no matter what they are, should be invisible. An app that gives you access to movies and TV shows online should not get in the way of your watching. On the contrary they should remove themselves from your experience as quickly as possible.

This is something I have learnt in creating my apps too. Rather than hiding the true content of the app behind menus and options I will endeavour to show the content of the app as the initial way in. The user doesn’t have to do anything to get to the content and that is the way it should be.

iOS Developer