CBPWordPress – Display content from your WordPress blog in an iOS app

CBPWordPress is an iOS library that will allow you to easily include content from a WordPress blog. The library can fetch lists of posts, individual posts and submit comments.

It is, of course, available on GitHub under the MIT License as well as via CocoaPods.

Background

Over the last few years, I’ve built an maintained the accompanying iOS app for Broadsheet.ie. It’s nearly tradition now for me to release a new version every year

The Example App

Included in the repo is an example app that is the basis for the new Broadsheet.ie app. This app will allow you to browse the site content, search for posts and submit comments.

The app also refreshes itself in the background, reminds the user of its existence in the morning and evenings and updates the logo on the home screen every 6 hours.

The full app includes Google Analytics and Mobile Ad SDK, Crashlytics and Conveser.io and has its own fork.

Installing the Plugin

Before you can use CBPWordPress, you must install the WP-JSON-API plugin to provide the data to the app. This is a slightly modified fork that provides a few extra fields to make things a bit smoother for the app.

If you want to be able to submit comments via the app, remember to turn on the Respond controller in the JSON API settings section.

Getting Started With The Example

Check out the repo from GitHub and initialise the Example pods:

git clone https://github.com/kmonaghan/CBPWordPress.git
cd CBPWordPress/Example
pod install

If you open the example project workspace and build and run the app, it should pull the latest 10 posts from Broadsheet.ie.

Using CBPWordPress In Your Own App

CocoaPods

The easiest way to use CBPWordPress is to install it via CocoaPods. To do that, just add the following line to your Podfile and then run ‘pod update’.

pod 'CBPWordPress'

Add the CBPWordPress project to your project

If you don’t use CocoaPods, add all the files in the CBPWordPress folder to your project. Then simply include the CBPWordPress.h header file where you want to use the library.

Note that you will also have to include AFNetworking in your project.

Usage

Pointing the library at your own WordPress installation is trivial. The first call to the library should be to set the root URL for the API.

[CBPWordPressAPIClient rootURI:@"http://YOUR-API-URL];

Once that is set, the calls to the API will use that URL.

Fetching A List Of Posts

To get a list of posts, you use the fetchPostsWithParams:withBlock: method from the NSURLSessionDataTask category.

In the example below, the first page of the recent posts is retrieved and the posts assigned to an array.

__weak typeof(self) weakSelf = self;

[NSURLSessionDataTask fetchPostsWithParams:@{@"page": @(1)}
withBlock:^(CBPWordPressPostsContainer *data, NSError *error) {
if (error) {
//Handle Error
return;
}

__strong typeof(weakSelf) strongSelf = weakSelf;

strongSelf.posts = data.posts;
}];

The allowed parameters are:

  • page: The page you want to fetch. Starts at 1.
  • count: The number of posts to retrieve. Defaults to 10.

Fetching A Post

If you know the post id, you can fetch a post using the fetchPostWithId:withBlock: method from the NSURLSessionDataTask category. The example below fetches post 1234 and assigns it to a local post variable.


__weak typeof(self) weakSelf = self;

[NSURLSessionDataTask fetchPostWithId:1234
withBlock:^(CBPWordPressPost *post, NSError *error){
if (error) {
//Handle Error
return;
}

__strong typeof(weakSelf) strongSelf = weakSelf;

strongSelf.post = post;
}];

If you have the URL of the post, you can use the fetchPostWithURL:withBlock: method instead. You pass the full URL of the post as the parameter.

Comment On A Post

To comment on a post, the postComment:withBlock: method from the NSURLSessionDataTask category is used. The method takes a CBPWordPressComment object as the first parameter. Below is an example comment being initialised.

CBPWordPressComment *newComment = [CBPWordPressComment new];
newComment.postId = 1234;
newComment.email = @"example@example.com";
newComment.name = @"Jonny Appleseed";
newComment.content = @"This is a comment!";
//Optional
newComment.url = @"http://somewebsite.com";
//If the comment is replying to another comment
newComment.parent = 1234;

Note that the URL and parent properties are optional but everything else is required. The parent property should be only be set if the user is replying to a comment and should be that comment’s id.

Once the comment is initialised, pass it to the postComment:withBlock: method. In the following example, the new comment is submitted and on success is set to the returned comment object.

__weak typeof(self) weakSelf = self;

[NSURLSessionDataTask postComment:newComment
withBlock:^(CBPWordPressComment *comment, NSError *error){
__strong typeof(weakSelf) strongSelf = weakSelf;

if (error) {
//Handle error
return;
}

strongSelf.comment = newComment;

Known issue: if WordPress detects a duplicate comment, the resulting return is HTML rather than JSON.

To Do

The library is very much a work in progress. Some of the planned functionality to add is:

  • Add option to fetch data from WP-API plugin
  • Implement helper methods for each WP-JSON-API endpoint (get_category_posts, get_tag_posts etc.)
  • Add a Today Extension to the example app

Contributing

Contributions via pull requests and suggestions are also welcome (although no promises that anything will be added).

If you do use this for your own app, I’d love to hear from you.

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.

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.

Your Broadsheet.ie Android app has arrived

Screenshot_2013-06-09-12-23-01

Finally, more than two and a half years after my iOS version was released I’ve built an Android app for Broadsheet.ie and it’s available now on the Google Play store.

The app doesn’t quite have feature parity with the iOS version but is close enough that it warrants release (especially considering the clamouring for it from the readers). I will be actively developing it over the summer in step with some updates to the iOS app.

The Android fragmentation issue means I’ve not been able to test it on all platforms, but I’ve made an effort to ensure it works on the top 10 devices that access the website. Hopefully the app won’t look too bad outside of these.

Think you can do better?

As with the iOS version of the app, the code is available on GitHub under the MIT license. I do this not in the hope that someone will come along and fix bugs or improve it but in case someone else finds it useful and wants to use it.

I would, of course, be delighted if someone actually did create a pull request…

And now over to you

The Android using section of our readers have been very vocal about wanting an app. When presented with evidence of lower engagement on the site from Android the lack of an app has been blamed (an opinion which I don’t subscribe too – it seems more like Android users don’t really use their devices compared to iOS).

The only way developers are going to take Android seriously is if people actually use their phones and download apps. So grab the app today and make this developer a happy man!

Eclipse, ADT, Maven, m2e, Android Connector setup

I’m looking at some Android development at the moment in work after being immersed in iOS development for the last few years. Switching tools always has a bit of a learning curve and this post documents what’ve setup so far. I’ve had a few false starts so this might come in useful to someone else.

Since pretty much everything I do these days app wise involved consuming some sort of REST API, I went looking for a library to handle that end of things. I came across Robospice which at first glance fits the bill for what I want. It uses Maven for project and dependency management.

As I’ve not really used Java I’ve never used Maven in anger and had some difficult in setting it up properly. While there are instructions out there, they all assume some working knowledge of how Eclipse, Maven or the ADT works so not ideal for a complete beginner. There was a lot of googling and reading Stack Overflow before it finally all worked.

Here’s the steps I followed to get it running on my iMac:

  • Download the Android SDK as the ADT bundle and install
  • Set the environment variable ANDROID_HOME to point to the sdk directory
  • Run ‘android update sdk –no-ui –all –force’ (android is under tools in the sdk folder. Also, this can take a while as it downloads everything)
  • Open ADT and install the Marketplace Client via ‘Install new software…’ under ‘Help’
  • Install Eclipse Plug-in Development Environment via ‘Install new software…’ under ‘Help’
  • Install M2E Plugin via ‘Install new software…’ under ‘Help’ using the URL http://download.eclipse.org/technology/m2e/releases
  • Install Maven 3 if you have an older version (or none) on your system (instructions on how to do so here)
  • Install Egit from the Eclipse Marketplace
  • Install Android Configurator from the Eclipse Marketplace (search for ‘android m2e’)

After all the restarts, you should be now at a stage where you can import Maven projects.

There’s a couple of more steps before you’re able to create a Maven project:

  • Start creating a new Maven Project
  • In ‘Select an Archetype’, click on ‘Add Archetype…’
  • Set ‘Archetype Group Id’ to ‘de.akquinet.android.archetypes’
  • Set ‘Archetype Artifact Id’ to ‘android-quickstart’
  • Set ‘Archetype Version’ to ‘1.0.8’

You can then continue on creating your project. Once it’s created you may see the error Project ‘skillpages-android’ is missing required source folder: ‘src/test/java’ “. This is a known issue and here’s two solutions to this:

  1. Create the directory and refresh the project
  2. Update the Android Configurator from the URL http://rgladwell.github.com/m2e-android/updates/master/

I will note that after I updated the plugin, it broke creating new projects for me.  But I’m not sure if that was something I did or an issue with it. I ended up removing and reinstalling it.

Hopefully this will help someone else bootstrap themselves into Android development and not just left fruitlessly searching.

Broadsheet.ie iPhone App 2.0

For the last few months I’ve been picking away at a new Broadsheet app for the iPhone.  It’s finally been released to world so it’s time to talk about it and some of the changes.

Raison D’être

The original version of the app was released in January 2011 and bar some minor bug fixes released in March 2011, it has gotten little attention since then.  While the app has been well received, there’s various bugs with commenting, sharing, post rendering and loading new posts.

The app also looks very tired and old compared to its peers so a bit of a more modern look wouldn’t go astray never mind the fact that none of the image assets were updated for retina displays.

What’s New

IMG_1714

IMG_1715

IMG_1719Straight off, for those on an iPhone 5, the app is no longer letterboxed.

There’s a new layout which disposes of the need for a tab bar by moving the information and tip tabs into the nav bar and eliminating of the gallery and video tabs.  The purpose gallery tab has disappeared as Broadsheet now posts galleries as images inline rather than using a javascript gallery.

The post archive is now searchable via a search bar which is hidden at the top of the post list.  While the search is powered by the not-great standard WordPress search, it does open up more content to the user.

Down on the bottom right there’s a fullscreen button.  This hides the status and navigation bars giving you an extra 64 pixels of space to gaze lovingly on the content.  When in fullscreen mode, there’s a little back arrow at the bottom left to help you navigate between screens.

Tapping an image in a post now brings you to that image in a gallery of all images associated with the post.  You can now easily zoom the image and swipe between the other images associated with the post.

IMG_1718IMG_1717

There’s no need to return to the post list screen to navigate between posts.  Dragging the screen down will load the next post while dragging up will load the previous.  This turns into an infinite scroll for posts as long as there are more posts to view.  The post list screen will also be updated with the extra posts.

The comment view is now threaded as well as rendering people’s avatars (which are generated from Gravatar) properly. Now all we have to do is get people to sign up for their own avatar.  Comments can also be replied to directly as well as creating new posts.

Touch me

A big change from the original app is the use of gestures through out for navigation.  Swiping left and right brings you between the post list, a post and the post comments.  This allows for quick and easy navigation.

Swiping left on a comment allows you to reply directly to it, providing a secondary access method to the reply button.

IMG_1710 IMG_1711
On a post screen, the available controls are revealed with a long touch, putting the buttons just above your finger tip. These allow you to view comments, make a comment and share the post.

A Bit of Help

IMG_1713

Gestures and hidden navigation is all well and good but it can be hard for users to discover.  This is easily solved with a couple of help screens which appear the first time you hit the post screen or go full screen.  These very quickly show you what you can do using some great gesture icons from Mobile Tuxedo.

Down The Line

There has been a consistent call for an iPad version of the app.  I have started on making the app universal (i.e. works on both iPhone and iPad from the same download) but for the initial release I decided that getting the iPhone version right was more important.  Hopefully I’ll complete the iPad changes over the next few months and release that as an update.

Other Platforms

An Android and Windows Mobile version of the app are in development and should be released soon.

You can download the app from the Apple App Store and if you have the previous app already installed you should be able to update.

Yet Another Searchable Property Price Register

Last Sunday, the Residential Property Price Register was launched.  Since I’m keeping an eye out for something to buy, I was fascinated by the details it contained.  But the search options were limited and there was no map.  However, the data was downloadable as a trio of CSV files.  So Yet Another Searchable Property Price Register was born.

I dumped all three files into a MySQL db, slapped a PHP script in front of it for searching and another to geocode the addresses and used Twitter bootstrap to give it a bit of spit and polish.  All in all it was a few hours work and another few hours to get the data geocoded.  It really leads me to ask what problems were encountered that resulted in it taking two years for the data to appear online.

If you want to have a look at the code or raw data, you can visit the repo on GitHub.  You’ll see a friend of mine, Mike McHugh has already helped make my rough version all the better.  I’ve included the database so people can submit improvements to the data.

Of course, it was such a good idea other people had it as well. They all put their own search interface onto the data and some did a few more interesting things.  The ones I’ve found so far are:

The head of the Property Services Regulatory Authority, Tom Lynch is quoted in an article in the Sunday Times (Home Truths, page 10 on 7/10/2012 – behind a paywall so I’m not bothering to link) as saying the don’t have additional information like square footage, number of bedrooms and other details that would truly make the information useful.  Yet Daft.ie’s version does just that using the data they have on hand.  Surely an interface could have been built for registering the houses that asked for these details (as well as actually validating the data and avoiding clangers like ‘Gawlay‘) when submitting for stamp duty.

It also seems odd that the official version didn’t consider mapping the data.  Even if they didn’t ask for the location when gather the data, services like Google’s Geocoding API (which I used) are available.  While not perfect,  it gives reasonable results most of the time.

It’s great to have the data, but there’s a lot more information that would give context and enhance what’s there.  Hopefully the criticisms  and improvements made by 3rd parties will be taken on board and a much improved version will appear in the near future.

Hopefully someone will find this useful and I’ll be updating the database as more data becomes available.