Skip to content

Upgrading from v0.10.x to v0.20.0

shir edited this page Jan 29, 2013 · 33 revisions

Using AFNetworking

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.

HTTP Headers

in 0.10:

RKObjectManager* objectManager = [RKObjectManager managerWithBaseURLString:url];
[objectManager.client setValue:@"foobar" forHTTPHeaderField:@"X-Custom-Header"];

in 0.20:

    RKObjectManager* objectManager = [RKObjectManager managerWithBaseURLString:url];
    [objectManager.HTTPClient setDefaultHeader:@"X-Custom-Header" value:@"foobar"];

Invalidate Cache

in 0.10:

    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    [objectManager.client.requestCache invalidateAll];

in 0.20:

    [ [NSURLCache sharedURLCache] removeAllCachedResponses]

Activity indicator

in 0.10:

    RKObjectManager* objectManager = [RKObjectManager managerWithBaseURLString:url];
    objectManager.client.requestQueue.showsNetworkActivityIndicatorWhenBusy = YES;

in 0.20:

    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;

Network Reachability Alert

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];
    }
}];

Adding routes to an object manager's route set

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]] ;

POSTing objects with file uploads

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.
    }];
    [objectManager enqueueObjectRequestOperation:operation];

Object Requests

GET objects with a loader block

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

Serialization has changed quite since the request and response have have 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"]];

Cancel all requests

in 0.10:

    [[RKClient sharedClient].requestQueue cancelAllRequests];

in 0.20:

    [[RKObjectManager sharedManager].operationQueue cancelAllOperations];

Core Data

TODO: summarize the changes.

Entity Mappings

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];

Mapping an Object Representation Directly

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];