Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Broadsheet.ie 2.0

Broadsheet.ie 2.0

A talk on the Broadsheet.ie app for Xcake:labs

Karl Monaghan

March 12, 2013
Tweet

More Decks by Karl Monaghan

Other Decks in Programming

Transcript

  1. • A Brief History • Justification • Technical Mumbo Jumbo

    • Future • Questions Tuesday 12 March 13
  2. • 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
  3. • 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. { 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: "<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='584' height='359' src='http://www.youtube.com/embed/ypBGI2_YXeo? version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0'></ iframe></span></p> <p>Oh.</p> <p>Dear.</p> <p>Fine Gael Senator Fidelma Healy Eames at the oireachtas hearing on social media.</p> <p><del>Script by Chris Morris.</del></p> <p>Transcript to follow.</p> <p><strong>Thanks Oireachtas Retort</strong></p> <p>&nbsp;</ p> <p>&nbsp;</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 &nbsp; &nbsp;", 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. [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
  15. 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
  16. - (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
  17. • 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
  18. • 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
  19. 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
  20. • 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
  21. 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
  22. • Both next and previous max out at their height

    - lets the user know that releasing will perform the action Tuesday 12 March 13
  23. - (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
  24. 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
  25. 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
  26. 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
  27. • We want your submissions • Irish App of the

    Day • Interesting Jobs • [email protected] Don’t Forget Tuesday 12 March 13