Replicating messages.app for fun, profit, and erosion of sanity


by Jack Flintermann
@jflinter


We're an offline social utility. Like going to a bar but better.
Key feature: great, real-time customer service by real people.
Before our app, we did this over SMS.

"It's a custom-designed, one-of-a-kind bespoke app I had built for my assistant and I to communicate through." - Dave Morin

Demo

Get the Data


1) Create message on server
- Deliver Push Notification via APNS
(bonus: UIBackgroundModes!)


2) Download message on device

- RestKit + AFNetworking


3) Store message locally

- Restkit + Core Data

COCOA TOUCH BEST FRIENDS

NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller; 

UITableView
- (void)beginUpdates;
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)endUpdates;

Update UI

NSFetchedResultsControllerDelegate -> UICollectionViewDatasource

- (void)performBatchUpdates:(void (^)(void))updates completion:(...)completion


- Annoyingly non-mapped to FRC

- NSBlockOperation helps manage complexity


Make things bounce


- Subclass UICollectionViewFlowLayout

- UIDynamicAnimator + UIAttachmentBehavior do the heavy lifting

- I used lots of other people's code for this


Here be Dragons

- Cache FRC changes before calling  performBatchUpdates:
- FRC doesn't give you 100% of updates
(i.e. adding a new section 0)
- Need advanced logic to add/remove dynamic behaviors from inserted/removed cells in layout
- Occasionally want to disable bouncy layout animations

Link Detection

- TTTAttributedLabel
- Extremely simple HTML parser via NSRegularExpression
- Very slow, requires caching of UICollectionView sizes
- Other option: NSHTMLTextDocumentType

Slide-to-dismiss keyboard

Options:
a) UIScrollViewKeyboardDismissModeInteractive
Pros: simple, written by Apple
Cons: Extremely limited/horrible API, really hard to support UITextField inside inputAccessoryView, bug in UIKeyboardFrameDidChangeNotification

b) DAKeyboardControl
Pros: It's exactly the API you want
Cons: Extraordinarily hackish, sometimes breaks on iOS7

Brief silly aside


// in viewDidLoad
tableView.transform = CGAffineTransformMakeRotation(M_PI);

// in cellForRowAtIndexPath:
cell.transform = CGAffineTransformMakeRotation(-M_PI); 


More Small Details

- HPGrowingTextView (grow the message text field as the user enters text)

FastImageCache (extremely fast image rendering)

- Group sections by sectionNameKeyPath

Colophon

Cocoapods:
AFNetworking, RestKit, TTTAttributedLabel, DAKeyboardControl, FastImageCache, HPGrowingTextView

Resources:

The end


Jack Flintermann
jack@joingrouper.com
@jflinter

Replicating messages.app for fun, profit, 

By Jack Flintermann

Replicating messages.app for fun, profit, 

  • 11,258