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
