IMG_2785

The Three Tun Tavern

There’s been a lot of interest in the office to see what the inside of the The Three Tun Tavern was actually like since they started renovating it a few months ago. Since today was the official opening, 10 of us headed down for lunch out of sheer nosiness.

Inside it seemed brighter and airier than the previous incarnation, Tonic. The bar has been moved from the center of the building to along the back wall, opening it up a lot more space. Some of the internal walls have been removed as well so there’s more overlooking the central area. The over all impression though wasn’t of a brand new pub, rather one relatively recently renovated but lived in.

There were an awful lot of staff on but it’s not clear if that’s just because it was opening day or will be the norm.  They were certainly needed today as there were a constant stream of customers coming in, as well as a few curious people just having a nose around.

IMG_2790

Chicken & Ribs Combo

IMG_2792

Sirloin of Rump Steak

Food wise, the menu is rather extensive albeit standard pub grub fare. They’ve various food ‘clubs’ on during the week with themed specials.

Being lazy and since it was their Tuesday Steak Club, I (and most of the rest of the guys) ended up having a rump steak and chips for €9.95 (it’s normally €12.95). A few more chips wouldn’t have gone astray and the steak was a tiny bit overcooked for rare but the meat was flavourful. Considering the price (which included a soft drink) it was good value.

It was opening day though, so there was the inevitable hiccup with one of the meals which left one of the guys waiting 30 minutes for his veggie burger. It’s probably a little unfair to judge them on this though since it was opening day.

Overall the consensus was that the food was fine and filling but nothing spectacular. It’s another lunchtime option for Blackrock, but you wouldn’t be going out of your way to eat there.

IMG_2789

I will be back at least once more though as they’ve a good selection of craft beers on tap that I’d like to try (and retry Hobgoblin to see if my college days impression of it being vile is true).

Okay so it’s a Wetherspoon’s pub but to be honest, it’s not particularly different to many pubs already operating here. It’s probably going to do a decent lunchtime trade from the off but I wouldn’t like to make predictions about the evening.

Creating an iOS Framework and Today Extension

One of the exciting new things announced at the WWDC keynote this month was App Extensions. This really opens up inter-app communication as well as letting developers do interesting things with the notification center and sharing.

I’m convinced that pretty much every news organisation is going have a widget included in their app to show the latest couple of stories. To that end, I’m going show here how I added a Today widget to a simplified version of the Broadsheet app.

All the code talked about here is available on GitHub under the MIT license.

Caveats:

  • This all works in the simulator but has not been tested on a device yet  Kindly tested by Liam Dunne and it works (phew!)
  • Some of the cell layouts are a bit off but are good enough for informational purposes
  • This is still all in Obj-C rather than being all cool and done in Swift

Starting off

Our starting point is a simple app that grabs the JSON feed of the latest 10 posts Broadsheet.ie and displays them in a UITableView. Tapping on a cell brings you to a screen that displays the content of the post in a UITextView (this will sometimes be mangled due to the content).

To this app we’re going to add a Today widget that displays the latest two post and brings you back to the app when a cell is tapped.

The base app is in the (imaginatively called) ‘baseapp‘ branch.

Creating The Framework

First, we’re going to create a framework to hold the common files that will be used by both the app and the widget. We need to add a framework target to the project by doing the following:

  • Select the project
  • Editor->Add Target
  • Select ‘Framework & Library’
  • Select ‘Cocoa Touch Framework’ and hit ‘Next’
  • Give it a name (ours is called CBPKit) and hit ‘Finish’

The framework should be automatically included in your app target (check under ‘Link Binary With Libraries’ in ‘Build Phases’).

Move any files you want your framework to provide from your app to the framework (note that this doesn’t move the files on disk). In this case it is everything but the view controllers.

Select the headers and in the ‘Utilities’ pane select your framework and set the option on the right to ‘project’.

Select the implementation files and again in the ‘Utilities’ pane select your framework and unselect your project.

For displaying the images in the cells, I’m using SDWebImage. I could have just add the relevant SDWebImage files to the framework I just created, but this seems wrong to me as:

  • You may include another framework in the future that includes and exposes SDWebImage and then you’d have a clash
  • You release your framework and someone can’t use it because your included version of SDWebImage clashes with the version they want to use
  • SDWebImage may release its own framework in the future

Instead, I created a separate framework (with the exact same steps as above) called SDWebImageKit.

As I may want to use this framework in another project, I set the headers to ‘Public’ in the ‘Utilities’ pane and added each of the headers to the framework header file. This means that I can import all the headers at once using:

#import <SDWebImageKit/SDWebImageKit.h>

When you run the app now, it should look no different to before despite the internal changes.

If you switch to the ‘framework‘ branch, you’ll see this built on top of the previous branch.

Today Extension

Like the framework, we first add a Extension target to the project.

  • Select the project
  • Editor->Add Target
  • Select ‘Application Extension’
  • Select ‘Today Extension’ and hit ‘Next’
  • Put in a name (ours is called CBPTodayExtensionExample) and hit ‘Next’
  • Go into Build Phases and include both the frameworks from above in the ‘Link Binary With Libraries’

If you run the project now in the simulator and pull down the notifications drawer, you should see ’1 New Widget Available’ at the very bottom. Tapping on ‘Edit’ will bring up all the available widgets and the new widget should be at the bottom with a green plus beside it. Tap the plus and it should be displayed with any other active widgets when you hit ‘Done’.

‘Hello world’ is a nice greeting but we want to replace this with a table containing 2 tappable cells containing the latest two posts from Broadsheet.

I don’t use storyboards, so I removed the default one added by the template. In info.plist I removed the key NSExtensionMainStoryboard and replaced it with NSExtensionPrincipalClass and put ‘TodayViewController’ as the value.

The cell I use in the app is a bit big for displaying in the notification center, so I added a set of new constraints to display a more compact cell. This means I can reuse the same data source and cell from the main app in my Today extension with just some minor modifications.

In the TodayViewController, there are two places that need to load data from the network – when the widget is created and when widgetPerformUpdateWithCompletionHandler is called. For the former, I load posts in viewDidLoad, so that they should be ready by the time the widget displays. When iOS thinks the widget will be displayed to the user after it has been first displayed, widgetPerformUpdateWithCompletionHandler is called giving the widget a chance to update the posts displayed.

In this example, both cells are always reloaded even if they already contain the posts returned. It probably shouldn’t do this and instead only replace the updated cells, but that’s a bit of extra polish I’ll leave for when building the full widget.

To get the app to open when a cell is tapped, a custom URL scheme is registered in the base app and this can be called using the UIViewController’s extensionContext to open the URL.

If you switch to the ‘todayextension‘ branch, you’ll see this built on top of the framework branch.

Finally

To keep everything tidy (and to satisfy my developer OCD), I used Synx to synchronise the files and folders to match those used in the project.

That’s all that’s needed to get a Today widget up and running. I’m delighted it’s so straight forward and I’m looking forward to seeing what people do with them.

Aside

There’s an issue with the debugger in Xcode attaching to the extension process properly. You can manually attach it by selecting ‘Debug’->’Attach to Process’ and finding the extension process under ‘System’. If your extension crashes on startup you won’t be able to this.

If you want to see logging from before you reattached the debugger, you can view it in the system log. You can open it from ‘Debug’->’Open System Log…’. If you filter it by your extension’s bundle id you’ll get the relevant entries.

Update 18/6/2014: In the release notes for Xcode 6 Beta 2 there’s a list of issues around the debugger and extensions. One pertinent to this app is that you can’t debug a today widget in the simulator but you can on device.

Update 7/7/2014: Xcode 6 Beta 3 came out today and fixes some of the debugging issues.

Recommended Reading and Viewing

AWS SNS and “File type is not supported or file has been corrupted”

I spent a rather frustrating few hours this morning trying to get push notifications set up on Amazon’s Simple Notification Service.

In the Getting Started with APNS, there is a section on converting the p12 formatted file exported from the key chain and converting it into pem format.

If you try and use this pem file in the management console, the following error is returned:

File type is not supported or file has been corrupted

What you actually need to upload is the p12 version.

Another post in the Wisdom of the Ancients series.

An Experiment In iOS App Pricing

I’ve a couple of paid apps and I am never really sure what to price them. On the one hand it’d be nice if I made anything from them but I also want people to actually use them. Last year, Michael Jurewitz wrote a series of fascinating posts on App Store Pricing. In particular the section on price elasticity stuck in my head.

My tax calculator app (unimaginatively called) TaxCalc.ie generally does best at two times of the year – in and around the budget announcements and in January (presumably as people are checking their first payslip).

On the run up to the 2014 Budget, I did a bigger than normal update to the app both modernising its internals and sprucing up the UI a bit. Based on the extra effort that was put in and keeping price elasticity in mind, I decided to increase the price on the 1st of October from 89c to €1.79 as a bit of an anti-sale.

For the period between the 1st of October 2013 and the 6th of January 2014 (€348.80 profit), I sold 320 copies compared to 315 the previous year (€151.20 profit). So not only did I sell more, I also more than doubled my profit.

I hadn’t really noticed this until I was doing my usual end of year comparisons at the start of January. As people seemed to be as willing to pay €1.79 as they were 89c, I decided to ratchet up the price to the next tier (€2.69) for the rest of January. The result was 72 sales compared to 101 in the same period of 2013. It may have been a 30% drop in downloads, but when you look at the proceeds, the app still generated more than twice amount at €118.08 as opposed to €54.54. I’d call that a successful experiment.

Will I increase the price again? Possibly for a week later in the year, but probably not. My gut feeling is that another price increase would would further drop download numbers to the point where it would make less money. More likely, I’ll either release the 2015 calculator as a standalone app or offer an update as an in-app purchase.

The tax calculator is a very niche app and and it’s really only providing me with beer money. Still, it was well worth tweaking the price to squeeze that little bit extra out of it to make the time spent developing it actually worth something.

tl;dr Increased the price of TaxCalc.ie from 89c to €1.79 and finally to €2.69 resulting in 2x profits while more or less maintaining the number downloads.

Broadsheet Yearly Stats 3: We’re getting a bit old in the tooth now.

So here we are again, another year, another gathering of stats from Broadsheet.ie. If I’m lucky, it’ll be in the Sunday Times again.

The Headline Figures

  • 4.9% increase in visits to 13.8 million
  • 5% drop in unique visitors to 2.9 million
  • 6.5% increase in pageviews to 30.1 million

So why the drop in unique users? We didn’t have another smash hit like the Meanwhile, At Smithfield Horse Fair. It provided a huge surge in once off visitors that we didn’t manage to replicate this year.

We’ve also not the had the massive growth of the previous couple of years, but that is somewhat expected. With the tiny team we have and a zero marketing budget, we’ve done extraordinarily well. Now we need to expand out from the core audience we’ve built.

Where Are You Based These Days?

There’s been no big change in where out visitors are from – Irish visitors account for 74% (up 2%), UK at 10% (no change), US 4.8% (down 0.3%), Germany 1.2% (up 0.13%) and Australia 1.12% (down 0.07%).

What Are You Reading?

Unlike previous years, the laughs are low on the top three stories so I’ll proceed without comment on those.

Instead I’m mention two of the more enduring pieces we ran from 2012 – Daisy: The Cutest Kitten In The World and the already mentioned Meanwhile, At Smithfield Horse Fair. Both of these pull in more once off visitors than most other posts from 2013.

How They’re Finding Us

Apart from the usual crowd that put in some form of ‘Broadsheet’, the top six search terms of 2013 were:

  • electric picnic 2013
  • property tax calculator
  • mikey clancy
  • tayto chocolate
  • niamh horan
  • bus porn

I’ve gone with six entries here rather than my usual five as, well, how could I resist exposing a term like “bus porn”? Niamh Horan continues to be popular for whatever reason.

The Window You Look At The Internet Through

Chrome continues to be the dominant browser choice with 39% (up 6%) of users viewing the site with it. Firefox stays in second place with 17.6% (down 4%), Safari takes third with 15.9% (down 0.1%) taking Internet Explorer’s place which now has 14.9% (down 2.9%).

iOS still accounts for 2/3rds of the mobile browser traffic to the site and Android taking most of the rest. The big winner though is Windows Phone from which pageviews exploded by 648% (for a total of 2.4% of the mobile traffic).

Apps

This year saw the release of an updated iOS app as well as new Android and Windows Phone apps.

There were 8,522 downloads on iOS (for about 30K total), 4,654 on Android and 2,310 on Windows Phone. From that, there’s between 2,500 and 3,000 active users a day producing 2.5 million sessions and 15 million screen views between them. It very much seems like people dip in and out of the apps a few times a day.

Anything Else?

If there’s anything else you’d like to know about, ask in the comments and I’ll see what I can dig out.

Previously:

A Broadsheet New Year
Broadsheet – Entering the Terrible Twos
A year in the Broadsheet

6 Tools In 5 Minutes, Or: How Not To Be A Caveman Developer


These are the slides from my talk at the XCake Xmas session.

Accessorizer:
http://www.kevincallahan.org/software/whatsNew.html
Download from the Mac App Store.

Objectify:
http://tigerbears.com/objectify/
Download from the Mac App Store.

Objective-Clean:
http://objclean.com/
Download from the Mac App Store.

Code Runner:
Download from the Mac App Store.

Reveal:
http://revealapp.com/

Tokens for Mac:
http://usetokens.com/

Getting your app reviewed on Broadsheet

After every post for Broadsheet’s App of the Day, there are a few emails about other apps to review. This is a guide for people who don’t have PR departments and are wondering what’s needed to get their app reviewed. I do look at every review request that comes in so don’t worry about it not being seen.

Submitting an App

All app submissions should be sent to broadsheet@broadsheet.ie. I’ll get them from there.

Your App

Tell me about it. What does it do? Why is it great? Who’s the audience? What devices/OS does it support? How much is it?

Include a link to it on the relevant app stores! Don’t make me search it out.

I have a selection of devices test on (iPhone 4s/5/5s, Samsung S3, Nexus 4) and I do test every app before review so if your app doesn’t work on one of these I’m afraid you’re out of luck.

Screenshots

If there’s particular screenshots that really show off your app, send them with your mail. If you don’t, I’ll first look at what you have on the app stores and possibly pick out something myself that captures my fancy.

The screenshots should have a max width of 400px (if they’re bigger we’ll resize them down ourselves).

Video

A video of your app is a great way explaining how your app works. The stand out in previous reviews is Soundwave.

Redemption Codes

If you’re submitting a paid app, a nice thing to do for the readers is to provided a few free versions. For iOS apps, I recommend Tokens to manage this.

Usually any codes put up are gone within minutes of the posts. On the downside, I’ve found the conversion rate for an unsuccessful redemption to a paying customer is practically nil.

Let me stress that this is completely optional and I don’t use any meant for the readers myself.

Canvassing Will Disqualify

As is always said at the bottom of the reviews, no favours, cuddles, or pints are given (or expected) for a review. If your app doesn’t make it, we probably just feel it doesn’t suit the content of the site.

Be Warned

The Broadsheet collective can be somewhat harsh. ParkYa got a bit of a savaging when they looked for beta testers but there’s usually a few nice people in the mix.

Slides from the talk “Face Detection and Recognition for Fun and Profit” for XCake

These are the slides to my talk for XCake on using OpenCV for face recognition on iOS. It should be noted that the first half of the talk deals with using OpenCV to also detect faces and so applies to any platform you can use OpenCV on. The simplified code sample on slide 14 should more or less work for you on non-iOS implementations.

Links

Slide 4: https://en.wikipedia.org/wiki/Prosopagnosia

Slide 6: http://opencv.org/

Slide 9: http://coding-robin.de/2013/07/22/train-your-own-opencv-haar-classifier.html

Slide 10: http://docs.opencv.org/modules/contrib/doc/facerec/facerec_tutorial.html

Slide 25: http://www.rekognition.com/
https://www.bioid.com/solutions/solutions-by-application/bioid-for-facedotcom.html
http://api.animetrics.com
http://www.identitykit.it/
http://www.skybiometry.com/

Slide 27: https://github.com/kmonaghan/FaceRecognition

Other

520 – What’s New in Camera Capture from WWDC 2012 talks about CIDetector and AVCaptureMetadataOutput from about the 19 minute mark. You should look at the sample code from that talk (StacheCam) for details on how to implement CIDetector and AVCaptureMedataOutput rather than the SquareCam project referenced in the Apple Documentation.

iOS 6, Auto Layout and MKMapView

I’m currently in the throws of updating an app for iOS 7. As part of the update, I’m throwing out all the XIBs and buying fully into using auto layout programatically.

I’ve been concentrating on getting it all to work on iOS 7 and only started at looking at how it looks on iOS 6 this week. Straight away I hit an issue

Auto Layout still required after executing -layoutSubviews. MKMapView's implementation of -layoutSubviews needs to call super.

The solution turns out to fairly straight forward. You don’t seem to be able to directly apply constraints between a MKMapView and another subview under iOS 6. Instead, you place your map into a container view and set the autoresizingMask to flexible width and height. You can then apply any constraints needed to the container view.

The code below simply creates a MKMapView which takes up the whole screen. From there, you could add buttons to the container view that are constrained to float 30 points from the bottom (which is what I needed to do).

self.mapContainerView = [[UIView alloc] initWithFrame:CGRectZero];
self.mapContainerView.translatesAutoresizingMaskIntoConstraints = NO;

self.mapView = [[MKMapView alloc] initWithFrame:self.mapContainerView.frame];
self.mapView.showsUserLocation = YES;
self.mapView.delegate = self;
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.mapContainerView addSubview:self.mapView];

[self.view addSubview:self.mapContainerView];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_mapContainerView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_mapContainerView)]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_mapContainerView]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_mapContainerView)]];

As an aside: Reveal has been invaluable in debugging my auto layout issues.

Slides From The Broadsheet Talk For Refresh Dublin

These are the slides from my talk in the Science Gallery for Refresh Dublin. All the links mentioned in the slides are below.

Top of the Posts

The top 5 posts (in reverse order):

What Got People Going?

The top 5 most commented posts (in reverse order):

The Apps

iPhone code: https://github.com/kmonaghan/KMWordPress
Android code: https://github.com/kmonaghan/Broadsheet.ie-Android

2013/7/30 Clarification on App Download numbers

The numbers shown are for the last 12 months (like the rest of the stats) not the total downloads. The iPhone app has around 27K total downloads which is why the user numbers are higher than the total downloads shown.