mobile in the cloud with diamonds. improved.
-
Upload
oleg-shanyuk -
Category
Technology
-
view
965 -
download
1
description
Transcript of mobile in the cloud with diamonds. improved.
MOBILE IN THE CLOUD WITH DIAMONDS
20132013
Cont
ent
Mobile & Cloud
Bicycles we ride
Essential frameworks
Advanced frameworks
Wondertools
You don't test me
Backends
Imagination
mobile and the internetsm
VS
FRAMEWORKS
★ faster ★ know how ★ solves the problem
★ tested ★ independent ★ supported
Developer’s dilemma
FRAMEWORKS
RESTawful services
That could be a pain
Core Data
Data and Cloud
Core Data
Data and Cloud
NSOperation
Core Data
Data and Cloud
NSOperation
NSURLConnection
Core Data
Data and Cloud
NSOperationNSURLConnection
AFNetworking
NSURL *url = [NSURL URLWithString:@"https://alpha-api.app.net/stream/0/posts/stream/global"];!NSURLRequest *request = [NSURLRequest requestWithURL:url];!AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {! NSLog(@"App.net Global Stream: %@", JSON);!} failure:nil];![operation start];
Core Data
Data and Cloud
NSOperationNSURLConnection
AFNetworking
KIT
REST
NSOperationNSURLConnection Core Data
Data and Cloud
AFNetworking KIT
REST
NSURLConnection
AFNetworking
NSOperation Core Data
KIT
REST Data Mapping
Data and Cloud - RestKit
RestKit example@interface RKTweet : NSObject!@property (nonatomic, copy) NSNumber *userID;!@property (nonatomic, copy) NSString *username;!@property (nonatomic, copy) NSString *text;!@end!!RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTweet class]];![mapping addAttributeMappingsFromDictionary:@{! @"user.name": @"username",! @"user.id": @"userID",! @"text": @"text"!}];!RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:nil];!NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"];!NSURLRequest *request = [NSURLRequest requestWithURL:url];!RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];! [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {! NSLog(@"The public timeline Tweets: %@", [result array]);!} failure:nil];![operation start];
@interface RKTweet : NSObject!@property (nonatomic, copy) NSNumber *userID;!@property (nonatomic, copy) NSString *username;!@property (nonatomic, copy) NSString *text;!@end!
RestKit example@interface RKTweet : NSObject!@property (nonatomic, copy) NSNumber *userID;!@property (nonatomic, copy) NSString *username;!@property (nonatomic, copy) NSString *text;!@end!!RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTweet class]];![mapping addAttributeMappingsFromDictionary:@{! @"user.name": @"username",! @"user.id": @"userID",! @"text": @"text"!}];!!RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:nil];!!NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"];!NSURLRequest *request = [NSURLRequest requestWithURL:url];!RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];! ![operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {! NSLog(@"The public timeline Tweets: %@", [result array]);!} failure:nil];![operation start];
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTweet class]];![mapping addAttributeMappingsFromDictionary:@{! @"user.name": @"username",! @"user.id": @"userID",! @"text": @"text"!}];
RestKit example@interface RKTweet : NSObject!@property (nonatomic, copy) NSNumber *userID;!@property (nonatomic, copy) NSString *username;!@property (nonatomic, copy) NSString *text;!@end!RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTweet class]];![mapping addAttributeMappingsFromDictionary:@{! @"user.name": @"username",! @"user.id": @"userID",! @"text": @"text"!}];!RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:nil];!NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"];!NSURLRequest *request = [NSURLRequest requestWithURL:url];!RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];! [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {! NSLog(@"The public timeline Tweets: %@", [result array]);!} failure:nil];![operation start];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:nil];!NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"];!NSURLRequest *request = [NSURLRequest requestWithURL:url];!RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];
RestKit example@interface RKTweet : NSObject!@property (nonatomic, copy) NSNumber *userID;!@property (nonatomic, copy) NSString *username;!@property (nonatomic, copy) NSString *text;!@end!RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTweet class]];![mapping addAttributeMappingsFromDictionary:@{! @"user.name": @"username",! @"user.id": @"userID",! @"text": @"text"!}];!RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:nil];!NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"];!NSURLRequest *request = [NSURLRequest requestWithURL:url];!RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];![operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {! NSLog(@"The public timeline Tweets: %@", [result array]);!} failure:nil];![operation start];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {! NSLog(@"The public timeline Tweets: %@", [result array]);!} failure:nil];![operation start];
RestKit example@interface RKTweet : NSObject!@property (nonatomic, copy) NSNumber *userID;!@property (nonatomic, copy) NSString *username;!@property (nonatomic, copy) NSString *text;!@end!RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTweet class]];![mapping addAttributeMappingsFromDictionary:@{! @"user.name": @"username",! @"user.id": @"userID",! @"text": @"text"!}];!RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:nil];!NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"];!NSURLRequest *request = [NSURLRequest requestWithURL:url];!RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];![operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {! NSLog(@"The public timeline Tweets: %@", [result array]);!} failure:nil];![operation start];
Next Step
NSURLConnection NSOperation Core Data
NSIncrementalStore
Next Step
NSURLConnection NSOperation Core Data
NSIncrementalStore
AFNetworking
Next Step
NSURLConnection NSOperation Core Data
NSIncrementalStoreAFNetworking
NSURLConnection
AFNetworking
NSOperation
NSIncrementalStore
Core Data
AFIncrementalStore
Next Step - Data Sync
a snap into AFIncrementalStore
YOUR CODE
CoreData framework
YOUR CODE
CoreData framework
+ AF
Incremental Store
AFNetworking
RESTful server
unusualusual
CoreData framework
working with AFIncrementalStore is the same as with CoreData
@interface TasksViewController()<NSFetchedResultsControllerDelegate>!@property NSFetchedResultsController *fetchedResultsController;!@end!!- (UITableViewCell *)tableView:(UITableView *)tableView! cellForRowAtIndexPath:(NSIndexPath *)indexPath !{!
...! [self configureCell:cell forRowAtIndexPath:indexPath];! return cell;!}!!- (void)configureCell:(UITableViewCell *)cell ! forRowAtIndexPath:(NSIndexPath *)indexPath !{! NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];! cell.textLabel.text = [managedObject valueForKey:@"text"];!
AFIncrementalStore
?
Business Logic
?
?
⦿Push Notifications ⦿InAppPurchase
⦿ Analytics ⦿ Passbook ⦿ Newsstand
Sync.
# helios server
with just one command...*
Helios-ready iOS frameworks
AFIncrementalStore Core Data Persistence with AFNetworking, Done Right
AFNetworking A Delightful iOS & OS X Networking Framework
Antenna Extensible Remote Logging
SkyLab Multivariate & A/B Testing
Orbiter Push Notification Registration
Cargo Bay The Essential StoreKit Companion
Ground Control Remote Configuration
Cocoa Pods$ [sudo] gem install cocoapods $ pod setup myproject$ pod install
http://cocoapods.org
Podfile example: platform :ios, '7.0' pod 'AFNetworking', '~> 2.0.3’ pod 'ICViewPager', '~> 1.5’ RestKit
AFNetworking AFIncrementalStore
AFAmazonS3Client ...
https://github.com/CocoaPods/Specs
Testing★ many frameworks comes with tests, bros
KIF
https://github.com/kif-framework/KIF
FRANK
https://github.com/moredip/Frank
KIF★ leveraging the accessibility attributes ★ conducted synchronously in the main thread ★ uses undocumented Apple APIs
- (void)testSuccessfulLogin!{! [tester enterText:@"[email protected]" intoViewWithAccessibilityLabel:@"Login User Name"];! [tester enterText:@"thisismypassword" intoViewWithAccessibilityLabel:@"Login Password"];! [tester tapViewWithAccessibilityLabel:@"Log In"];!! // Verify that the login succeeded! [tester waitForTappableViewWithAccessibilityLabel:@"Welcome"];!}
FRANK★ from outer ruby space ‘cucumber’ ★ 'Selenium for native iOS apps'. ★ uses undocumented Apple APIs ★ totally different approach to testing in iOS
Feature: Various scenarios that exercise different parts of Frank!!Background:! Given I launch the app !!Scenario: Counting number of rows in a table section! Then I should see 3 rows in section 0!!Scenario: Scrolling to the bottom of the table ! When I touch "Larry Stooge"! And I touch "User Roles"! Then I should not see "Returns"! When I scroll to the bottom of the table! Then I should see "Returns"
READY TO USE CLOUDS★Deployd.com
- free to use - javascript based
★★Parse.com -all essential platforms supported -“out of the box” basic data entities -free to test
★★★APIgee.com (books & webcasts) - developer console to popular services - intermediate data processing (eg.
convert xml to json, mapping, etc) - free to test
[email protected]@gelosi - http://obrij.com
AFNetworking, AFIncrementalStore, AF*** https://github.com/helios-framework/helios
RESTKit - https://github.com/RestKit/RestKit
Follow: @mattt, @soffes, @gruber, @edog1203
CocoaPods - http://cocoapods.org