Slide 1

Slide 1 text

The Long Overdue Update Tuesday 12 March 13

Slide 2

Slide 2 text

• A Brief History • Justification • Technical Mumbo Jumbo • Future • Questions Tuesday 12 March 13

Slide 3

Slide 3 text

• Software developer 14 years • Mainly ObjC now, but was PHP for a long time • Originally involved to ‘just’ set up the site (a single day of work he said) • Sucked in to maintain it and write posts • Do it out of the goodness of my soft heart And You Are...? Tuesday 12 March 13

Slide 4

Slide 4 text

• First released January 2011 • Used Three20 (yes, yes I’ve heard it all) • Spun out of another app that required WordPress integration • Dev time ~week • Generalised the library and released on GitHub as TTWordPress Brand New Retro Tuesday 12 March 13

Slide 5

Slide 5 text

Brand New Retro • A few updates in the first couple of months • Adding/Removing 2011 Election • Some bug fixing • Adding Flurry for some metrics • 20K downloads (http://karlmonaghan.com/ app-stats/stats.html? apple_identifier=413093424) • Dead since then despite bugs/feature requests Tuesday 12 March 13

Slide 6

Slide 6 text

What Do You Mean “You Weren’t Invited”? • From 1st February 2012 to 28th February 2013 2.3 million mobile visitors to the Broadsheet.ie website 1% 27% 1% 71% iOS Blackberry Android Windows Phone • Missing Android market in full effect Tuesday 12 March 13

Slide 7

Slide 7 text

We Don’t Usually Do This • iPhone 5 • Wanted to play around with a few libraries • No real metrics • Bug squashing • New features • Keeps me off the streets and out of trouble Tuesday 12 March 13

Slide 8

Slide 8 text

Meanwhile, in the backend • Website a WordPress blog (obviously) • API provided by the JSON API plugin (http://wordpress.org/extend/plugins/json- api/) • Own fork to provide some additional fields and clean up output (https://github.com/ kmonaghan/wp-json-api) Tuesday 12 March 13

Slide 9

Slide 9 text

{ 1 status: "ok", 2 post: { 1 id: 206619, 2 type: "post", 3 slug: "fidelma-the-frape-tape", 4 url: "http://www.broadsheet.ie/2013/03/06/fidelma-the-frape-tape/", 5 status: "publish", 6 title: "Fidelma: The Frape Tape", 7 title_plain: "Fidelma: The Frape Tape", 8 content: "

iframe>

Oh.

Dear.

Fine Gael Senator Fidelma Healy Eames at the oireachtas hearing on social media.

Script by Chris Morris.

Transcript to follow.

Thanks Oireachtas Retort

  p>

 

", 9 excerpt: "Oh. Dear. Fine Gael Senator Fidelma Healy Eames at the oireachtas hearing on social media. Script by Chris Morris. Transcript to follow. Thanks Oireachtas Retort    ", 10 date: "2013-03-06 15:17:04", 11 modified: "2013-03-06 15:17:04", 12 categories: [], 13 tags: [], 14 author: {}, 15 comments: [], 16 attachments: [ ], 17 comment_count: 12, 18 comment_status: "open", 19 previous_title: "A Limerick A Day", 20 previous_url: "http://www.broadsheet.ie/2013/03/06/a-limerick-a-day-120/", 21 next_title: "The Damn Hipster Guide To Dublin", 22 next_url: "http://www.broadsheet.ie/2013/03/06/the-damn-hipster-guide-to-dublin/" 3 }, 4 previous_url: "http://www.broadsheet.ie/2013/03/06/a-limerick-a-day-120/", 5 next_url: "http://www.broadsheet.ie/2013/03/06/the-damn-hipster-guide-to-dublin/" } http://www.broadsheet.ie/2013/03/06/fidelma-the-frape- tape/?json=1 Tuesday 12 March 13

Slide 10

Slide 10 text

You May Like This • Post list much more image centric • Searchable • Navigate between posts from post screen • Comments are threaded • Change font size • Submit photos • Fullscreen mode Tuesday 12 March 13

Slide 11

Slide 11 text

Tuesday 12 March 13

Slide 12

Slide 12 text

All the Gestures! • Wanted to be able to do as much as possible without buttons • Can swipe between post list, a post and comments • Not completely obvious so put in help screens • Few seem to have read the help Tuesday 12 March 13

Slide 13

Slide 13 text

Ah Here •The view comments/make comments/ share controls is too well hidden •Inspired by Summly’s hidden buttons •Always available where your thumb is sitting •Quick access to everything you need Tuesday 12 March 13

Slide 14

Slide 14 text

Tuesday 12 March 13

Slide 15

Slide 15 text

Pull/Drag to load with a UIWebView • UIWebView is essentially a dynamically resizing UIScrollView • Your favourite Pull-to-refresh solution probably works out of the box • Dragging from the bottom on the other hand... Tuesday 12 March 13

Slide 16

Slide 16 text

Pull/Drag to load with a UIWebView • Don’t know the content size until fully loaded • Don’t know when the UIWebView will stop loading • Size will change as assets are loaded Tuesday 12 March 13

Slide 17

Slide 17 text

[self.view addSubview:self.loadNextView]; [self.view addSubview:self.loadPreviousView]; [self.view addSubview:self.webView]; • Add the next/previous UIViews first • Add the UIWebView which has a transparent background • This is so the scroll bar overlays our next/ previous UIViews Tuesday 12 March 13

Slide 18

Slide 18 text

self.scrollView = self.webView.scrollView; self.scrollView.delegate = self; [self.scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionPrior context:NULL]; • Grab the UIWebView’s UIScrollView property • Set the delegate • Add an observer for changes to the content offset Tuesday 12 March 13

Slide 19

Slide 19 text

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context: (void *)context { if ([keyPath isEqualToString:@"contentOffset"]) { if (self.scrollView.contentOffset.y == 0) { self.loadNextView.frame = CGRectMake(0, -50.0f, self.view.frame.size.width, 50.0f); self.loadPreviousView.frame = CGRectMake(0, self.view.frame.size.height, 320.0f, 50.0f); return; } if (self.scrollView.contentOffset.y < 0) { CGFloat offset = self.scrollView.contentOffset.y; if (offset < -50.0f) offset = -50.0f; self.loadNextView.frame = CGRectMake(0, 0 - (50.0f + offset) ,self.view.frame.size.width, 50.0f); } else if (self.view.frame.size.height > (self.scrollView.contentSize.height - self.scrollView.contentOffset.y)) { CGFloat top = (self.view.frame.size.height - (self.view.frame.size.height - (self.scrollView.contentSize.height - self.scrollView.contentOffset.y))); if (top < (self.view.frame.size.height - 75.0f)) top = (self.view.frame.size.height - 75.0f); self.loadPreviousView.frame = CGRectMake(0, top , self.view.frame.size.width, 50.0f); } } } Tuesday 12 March 13

Slide 20

Slide 20 text

• If the contentOffset is 0, set the y co- ordinate of the next UIView to be -height and for the previous UIView the height of the containing UIView if (self.scrollView.contentOffset.y == 0) { self.loadNextView.frame = CGRectMake(0, -50.0f, self.view.frame.size.width, 50.0f); self.loadPreviousView.frame = CGRectMake(0, self.view.frame.size.height, 320.0f, 50.0f); return; } Tuesday 12 March 13

Slide 21

Slide 21 text

• If the contentOffset is less than 0, set the y co-ordinate of the next UIView to be - (height + contentOffset) • If the contentOffset is greater than the height of the next UIView, y is be set to 0 Tuesday 12 March 13

Slide 22

Slide 22 text

if (self.scrollView.contentOffset.y < 0) { CGFloat offset = self.scrollView.contentOffset.y; if (offset < -self.loadNextView.frame.size.height) offset = -self.loadNextView.frame.size.height; self.loadNextView.frame = CGRectMake(0, 0 - (50.0f + offset), self.view.frame.size.width, self.loadNextView.frame.size.height); } Tuesday 12 March 13

Slide 23

Slide 23 text

• If the height of the containing frame is greater than the height of the contentSize less the contentOffset, set the y co- ordinate of the previous UIView to the difference between the frame height and the frame height less the difference between the contentSize and contentOffset Tuesday 12 March 13

Slide 24

Slide 24 text

else if (self.view.frame.size.height > (self.scrollView.contentSize.height - self.scrollView.contentOffset.y)) { CGFloat top = (self.view.frame.size.height - (self.view.frame.size.height - (self.scrollView.contentSize.height - self.scrollView.contentOffset.y))); if (top < (self.view.frame.size.height - self.loadPreviousView.frame.size.height)) top = (self.view.frame.size.height - self.loadPreviousView.frame.size.height); self.loadPreviousView.frame = CGRectMake(0, top, self.view.frame.size.width, self.loadPreviousView.frame.size.height); } Tuesday 12 March 13

Slide 25

Slide 25 text

• Both next and previous max out at their height - lets the user know that releasing will perform the action Tuesday 12 March 13

Slide 26

Slide 26 text

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (scrollView.contentOffset.y <= -50.0f) { [self loadNext]; } else if ((self.view.frame.size.height - self.loadPreviousView.frame.origin.y) >= 75.0f) { [self loadPrevious]; } } • The appropriate action is performed when the UIScrollView stops being dragged Tuesday 12 March 13

Slide 27

Slide 27 text

Using The App, literally minutes ago • 8,649 updates, 465 downloads • Minor spike in downloads (triple the average to an entire 90 on day of release) • 4,603 active users (92% returning) • 56,796 sessions (3:02 minutes a session) • 329,121 screen views (33K to 41K a weekday) • 91% using iOS 6 Tuesday 12 March 13

Slide 28

Slide 28 text

Sure Where Would You Get It? • https://github.com/kmonaghan/ KMWordPress • MIT Licensed • Love to hear from anyone that does use it Tuesday 12 March 13

Slide 29

Slide 29 text

Things That Look Like The Broadsheet.ie App • iPad version • Android and Windows Phone in development • Release date of “when they’re ready” Tuesday 12 March 13

Slide 30

Slide 30 text

Tuesday 12 March 13

Slide 31

Slide 31 text

Tuesday 12 March 13

Slide 32

Slide 32 text

• We want your submissions • Irish App of the Day • Interesting Jobs • broadsheet@broadsheet.ie Don’t Forget Tuesday 12 March 13

Slide 33

Slide 33 text

@karlmonaghan http://karlmonaghan.com http://github.com/kmonaghan Tuesday 12 March 13