-
Notifications
You must be signed in to change notification settings - Fork 0
Upgrading from v0.10.x to v0.20.0
One of the big changes is that the custom networking code has been dropped and replaced by the widely used AFNetworking library. This means RKClient
and related classes are no longer part of RestKit.
The delegate protocols RKRequestDelegate
and RKObjectLoaderDelegate
have been removed from the project in favor of block based approaches. The most common, required methods of these protocols such as request:didLoadResponse:
, request:didLoadError:
, objectLoader:didLoadObjects:
, and objectLoader:didLoadError:
have been replaced with completion blocks on the AFHTTPRequestOperation
and RKObjectRequestOperation
classes. In general, these completion blocks are specified as a pair of success
and failure
blocks:
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
// This is the success block
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
// This is the failure block
}];
[operation start];
See the API Docs for more information.
Aside from the basic success/failure scenarios, AFNetworking exposes many common tasks via the AFHTTPURLConnection
class, which is the superclass of AFHTTPRequestOperation
and implements the NSURLConnectionDelegate
and NSURLConnectionDataDelegate
protocols. You can utilize these blocks and subclassing strategies to accomplish all other tasks that were previously done via RKRequest
or RKObjectLoader
.
Additional detail about the specific interactions between RestKit, AFNetworking, and NSURLConnection are explored in detail in the AFNetworking Integration guide.
in 0.10:
RKObjectManager* objectManager = [RKObjectManager managerWithBaseURLString:url];
[objectManager.client setValue:@"foobar" forHTTPHeaderField:@"X-Custom-Header"];
in 0.20:
RKObjectManager* objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:url]];
[objectManager.HTTPClient setDefaultHeader:@"X-Custom-Header" value:@"foobar"];
in 0.10:
RKObjectManager *objectManager = [RKObjectManager sharedManager];
[objectManager.client.requestCache invalidateAll];
in 0.20:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
in 0.10:
RKObjectManager* objectManager = [RKObjectManager managerWithBaseURLString:url];
objectManager.client.requestQueue.showsNetworkActivityIndicatorWhenBusy = YES;
in 0.20:
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
In 0.10:
objectManager.client.serviceUnavailableAlertEnabled = YES;
In 0.20:
[objectManager.HTTPClient setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
if (status == AFNetworkReachabilityStatusNotReachable) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No network connection"
message:@"You must be connected to the internet to use this app."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
}];
in 0.10:
[objectManager.router
routeClass:[Activity class]
toResourcePath:@"/activity/:identifier"] ;
[objectManager.router
routeClass:[Activity class]
toResourcePath:@"/activity"
forMethod:RKRequestMethodPOST] ;
in 0.20:
[objectManager.router.routeSet addRoute:[RKRoute
routeWithClass:[Activity class]
pathPattern:@"/activity/:identifier"
method:RKRequestMethodGET]] ;
[objectManager.router.routeSet addRoute:[RKRoute
routeWithClass:[Activity class]
pathPattern:@"/activity"
method:RKRequestMethodPOST]] ;
The sample code assumes you've registered a POST route for your object in the object manager's route set. See "Adding routes to an object manager's route set" above.
in 0.10:
RKObjectManager *mgr = [RKObjectManager sharedManager];
[mgr postObject:obj usingBlock:^(RKObjectLoader *loader) {
RKParams* params = [RKParams params];
[params setValue:obj.name forParam:@"expense[name]"];
[params setValue:obj.amount forParam:@"expense[amount]"];
RKParamsAttachment *attachment = [params setData:UIImageJPEGRepresentation(obj.photo, 0.7)
MIMEType:@"image/jpeg"
forParam:@"expense[photo_file]"];
attachment.fileName = @"image.jpg";
loader.params = params;
// What ever success handler you need.
loader.onDidLoadObject = ^(id loaded) {
NSLog(@"%@", loaded);
};
}];
in 0.20:
// But this time assuming you registered a RKRequestDescriptor to handle
// serializing the other fields.
RKObjectManager *objectManager = [RKObjectManager sharedManager];
NSMutableURLRequest *request =
[objectManager multipartFormRequestWithObject:obj method:RKRequestMethodPOST
path:nil parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
[formData appendPartWithFileData:UIImageJPEGRepresentation(obj.photo, 0.7)
name:@"expense[photo_file]"
fileName:@"photo.jpg"
mimeType:@"image/jpeg"];
}];
RKObjectRequestOperation *operation =
[objectManager objectRequestOperationWithRequest:request
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
// Success handler.
NSLog(@"%@", [mappingResult firstObject]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
// Error handler.
}];
The big change is the lack of a loader object and the new more consistent callback signature with RKMappingResult wraps the results of the mapping.
In 0.10:
[ [RKObjectManager sharedManager] loadObjectsAtResourcePath:@"/examples" usingBlock:^(RKObjectLoader *loader) {
loader.onDidLoadObjects = ^(NSArray *objects) {
NSLog(@"It Worked: %@", objects);
};
loader.onDidFailWithError = ^(NSError *error) {
NSLog(@"It Failed: %@", error);
};
}];
In 0.20:
[RKObjectManager.sharedManager getObjectsAtPath:path parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
NSLog(@"It Worked: %@", [mappingResult array]);
// Or if you're only expecting a single object:
NSLog(@"It Worked: %@", [mappingResult firstObject]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"It Failed: %@", error);
}];
Serialization has changed quite a bit since the request and response have separate mappings.
In 0.10:
RKObjectMapping *serialization = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[serialization mapKeyPath:@"amount" toAttribute:@"reimbursal[amount]"];
[serialization mapKeyPath:@"fromUserId" toAttribute:@"reimbursal[from_user_id]"];
[serialization mapKeyPath:@"toUserId" toAttribute:@"reimbursal[to_user_id]"];
[provider setSerializationMapping:serialization forClass:[RMReimbursal class]];
In 0.20:
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromDictionary:@{
@"amount": @"amount",
@"fromUserId": @"from_user_id",
@"toUserId": @"to_user_id",
}];
[objectManager addRequestDescriptor:
[RKRequestDescriptor requestDescriptorWithMapping:requestMapping
objectClass:[RMReimbursal class]
rootKeyPath:@"reimbursal"]];
in 0.10:
[[RKClient sharedClient].requestQueue cancelAllRequests];
in 0.20:
[[RKObjectManager sharedManager].operationQueue cancelAllOperations];
TODO: summarize the changes.
In 0.10:
// Defined elsewhere:
RKMapping *userMapping;
RKManagedObjectStore *objectStore
// The meat of it:
RKEntityMapping* mapping = [RKEntityMapping
mappingForEntityForName:@"RMHousehold"
inManagedObjectStore:objectStore];
mapping.primaryKeyAttribute = @"householdId";
[mapping mapKeyPath:@"id" toAttribute:@"householdId"];
[mapping mapKeyPath:@"display_name" toAttribute:@"displayName"];
[mapping mapKeyPath:@"users" toRelationship:@"users"
withMapping:userMapping];
In 0.20:
// Defined elsewhere:
RKMapping *userMapping;
RKManagedObjectStore *objectStore;
RKEntityMapping* mapping = [RKEntityMapping
mappingForEntityForName:@"RMHousehold"
inManagedObjectStore:objectStore];
mapping.identificationAttributes = @[@"householdId"] ;
[mapping addAttributeMappingsFromDictionary:@{
@"id": @"householdId",
@"display_name": @"displayName",
}];
RKRelationshipMapping *userRelationship =
[RKRelationshipMapping relationshipMappingFromKeyPath:@"users"
toKeyPath:@"users"
withMapping:userMapping];
[mapping addPropertyMapping:userRelationship];
In 0.10
[RKManagedObjectMapping mappingForClass:[RMHousehold class]
inManagedObjectStore:[RKObjectManager sharedManager].objectStore];
In 0.20
[RKEntityMapping mappingForEntityForName:@"RMHousehold"
inManagedObjectStore:[RKObjectManager sharedManager].managedObjectStore];
In 0.10
RKManagedObjectStore *managedObjectStore =
[RKManagedObjectStore managedObjectStoreWithStoreFilename:storeFilename];
In 0.20
self.objectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]];
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"StoreFileName.sqlite"];
[self.objectStore addSQLitePersistentStoreAtPath:path
fromSeedDatabaseAtPath:nil
withConfiguration:nil
options:@{
NSInferMappingModelAutomaticallyOption: @YES,
NSMigratePersistentStoresAutomaticallyOption: @YES
}
error:nil];
[self.objectStore createManagedObjectContexts];
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[SomeClass class]];
[mapping addAttributeMappingsFromDictionary:@{ @"id": @"someClassID", @"name": @"name" }];
NSDictionary *objectRepresentation = @{ @"id": @(12345), @"name": @"Some Name" };
SomeClass *someObject = [SomeClass new];
RKMappingOperation *operation = [[RKMappingOperation alloc] initWithSourceObject:objectRepresentation destinationObject:someObject mapping:mapping];
RKObjectMappingOperationDataSource *dataSource = [RKObjectMappingOperationDataSource new];
operation.dataSource = dataSource;
[operation start];
In 0.10
NSString *directory = [RKDirectory applicationDataDirectory];
In 0.20
NSString *directory = RKApplicationDataDirectory();