RestKit is a framework for consuming and modeling RESTful web resources on iOS and OS X

Related tags

Networking RestKit
Overview

RestKit

Build Status Pod Version Pod Platform Pod License Visit our IRC channel

RestKit is a modern Objective-C framework for implementing RESTful web services clients on iOS and Mac OS X. It provides a powerful object mapping engine that seamlessly integrates with Core Data and a simple set of networking primitives for mapping HTTP requests and responses built on top of AFNetworking. It has an elegant, carefully designed set of APIs that make accessing and modeling RESTful resources feel almost magical. For example, here's how to access the Twitter public timeline and turn the JSON contents into an array of Tweet objects:

@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 method:RKRequestMethodAny 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];

Getting Started

Overview

RestKit is designed to be modular and each module strives to maintain a minimal set of dependencies across the framework and with the host platform. At the core of library sits the object mapping engine, which is responsible for transforming objects between representations (such as JSON/XML <-> local domain objects).

Object Mapping Fundamentals

The object mapping engine is built on top of the Key-Value Coding (KVC) informal protocol that is foundational to numerous Cocoa technologies such as key-value observing, bindings, and Core Data. Object mappings are expressed as pairs of KVC key paths that specify the source and destination attributes or relationships that are to be transformed.

RestKit leverages the highly dynamic Objective-C runtime to infer the developers desired intent by examining the type of the source and destination properties and performing appropriate type transformations. For example, given a source key path of created_at that identifies a string within a parsed JSON document and a destination key path of creationDate that identifies an NSDate property on a target object, RestKit will transform the date from a string into an NSDate using an NSDateFormatter. Numerous other transformations are provided out of the box and the engine is pluggable to allow the developer to define new transformations or replace an existing transformation with a new implementation.

The mapper fully supports both simple attribute as well as relationship mappings in which nested to-one or to-many child objects are mapped recursively. Through relationship mappings, one object mapping can be added to another to compose aggregate mappings that are capable of processing arbitrarily complex source documents.

Object mapping is a deep topic and is explored in exhaustive detail in the Object Mapping Guide on the wiki.

API Quickstart

RestKit is broken into several modules that cleanly separate the mapping engine from the HTTP and Core Data integrations to provide maximum flexibility. Key classes in each module are highlighted below and each module is hyperlinked to the README.md contained within the source code.

Object Mapping
RKObjectMapping Encapsulates configuration for transforming object representations as expressed by key-value coding keypaths.
RKAttributeMapping Specifies a desired transformation between attributes within an object or entity mapping in terms of a source and destination key path.
RKRelationshipMapping Specifies a desired mapping of a nested to-one or to-many child objects in terms of a source and destination key path and an RKObjectMapping with which to map the attributes of the child object.
RKDynamicMapping Specifies a flexible mapping in which the decision about which RKObjectMapping is to be used to process a given document is deferred to run time.
RKMapperOperation Provides an interface for mapping a deserialized document into a set of local domain objects.
RKMappingOperation An NSOperation that performs a mapping between object representations using an RKObjectMapping.
Networking
RKRequestDescriptor Describes a request that can be sent from the application to a remote web application for a given object type.
RKResponseDescriptor Describes an object mappable response that may be returned from a remote web application in terms of an object mapping, a key path, a SOCKit pattern for matching the URL, and a set of status codes that define the circumstances in which the mapping is appropriate for a given response.
RKObjectParameterization Performs mapping of a given object into an NSDictionary representation suitable for use as the parameters of an HTTP request.
RKObjectRequestOperation An NSOperation that sends an HTTP request and performs object mapping on the parsed response body using the configurations expressed in a set of RKResponseDescriptor objects.
RKResponseMapperOperation An NSOperation that provides support for object mapping an NSHTTPURLResponse using a set of RKResponseDescriptor objects.
RKObjectManager Captures the common patterns for communicating with a RESTful web application over HTTP using object mapping including:
  • Centralizing RKRequestDescriptor and RKResponseDescriptor configurations
  • Describing URL configuration with an RKRouter
  • Serializing objects and sending requests with the serialized representations
  • Sending requests to load remote resources and object mapping the response bodies
  • Building multi-part form requests for objects
RKRouter Generates NSURL objects from a base URL and a set of RKRoute objects describing relative paths used by the application.
RKRoute Describes a single relative path for a given object type and HTTP method, the relationship of an object, or a symbolic name.
Core Data
RKManagedObjectStore Encapsulates Core Data configuration including an NSManagedObjectModel, a NSPersistentStoreCoordinator, and a pair of NSManagedObjectContext objects.
RKEntityMapping Models a mapping for transforming an object representation into a NSManagedObject instance for a given NSEntityDescription.
RKConnectionDescription Describes a mapping for establishing a relationship between Core Data entities using foreign key attributes.
RKManagedObjectRequestOperation An NSOperation subclass that sends an HTTP request and performs object mapping on the parsed response body to create NSManagedObject instances, establishes relationships between objects using RKConnectionDescription objects, and cleans up orphaned objects that no longer exist in the remote backend system.
RKManagedObjectImporter Provides support for bulk mapping of managed objects using RKEntityMapping objects for two use cases:
  1. Bulk importing of parsed documents into an NSPersistentStore.
  2. Generating a seed database for initializing an application's Core Data store with an initial data set upon installation.
Search
RKSearchIndexer Provides support for generating a full-text searchable index within Core Data for string attributes of entities within an application.
RKSearchPredicate Generates an NSCompoundPredicate given a string of text that will search an index built with an RKSearchIndexer across any indexed entity.
Testing
RKMappingTest Provides support for unit testing object mapping configurations given a parsed document and an object or entity mapping. Expectations are configured in terms of expected key path mappings and/or expected transformation results.
RKTestFixture Provides an interface for easily generating test fixture data for unit testing.
RKTestFactory Provides support for creating objects for use in testing.

Examples

Object Request

// GET a single Article from /articles/1234.json and map it into an object
// JSON looks like {"article": {"title": "My Article", "author": "Blake", "body": "Very cool!!"}}
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Article class]];
[mapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/articles/:articleID" keyPath:@"article" statusCodes:statusCodes];

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://restkit.org/articles/1234.json"]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
    Article *article = [result firstObject];
	NSLog(@"Mapped the article: %@", article);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
	NSLog(@"Failed with error: %@", [error localizedDescription]);
}];
[operation start];

Managed Object Request

// GET an Article and its Categories from /articles/888.json and map into Core Data entities
// JSON looks like {"article": {"title": "My Article", "author": "Blake", "body": "Very cool!!", "categories": [{"id": 1, "name": "Core Data"]}
NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
NSError *error = nil;
BOOL success = RKEnsureDirectoryExistsAtPath(RKApplicationDataDirectory(), &error);
if (! success) {
    RKLogError(@"Failed to create Application Data Directory at path '%@': %@", RKApplicationDataDirectory(), error);
}
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"Store.sqlite"];
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
if (! persistentStore) {
    RKLogError(@"Failed adding persistent store at path '%@': %@", path, error);
}
[managedObjectStore createManagedObjectContexts];

RKEntityMapping *categoryMapping = [RKEntityMapping mappingForEntityForName:@"Category" inManagedObjectStore:managedObjectStore];
[categoryMapping addAttributeMappingsFromDictionary:@{ "id": "categoryID", @"name": "name" }];
RKEntityMapping *articleMapping = [RKEntityMapping mappingForEntityForName:@"Article" inManagedObjectStore:managedObjectStore];
[articleMapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];
[articleMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"categories" toKeyPath:@"categories" withMapping:categoryMapping]];

NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:articleMapping method:RKRequestMethodAny pathPattern:@"/articles/:articleID" keyPath:@"article" statusCodes:statusCodes];

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://restkit.org/articles/888.json"]];
RKManagedObjectRequestOperation *operation = [[RKManagedObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];
operation.managedObjectContext = managedObjectStore.mainQueueManagedObjectContext;
operation.managedObjectCache = managedObjectStore.managedObjectCache;
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
  Article *article = [result firstObject];
	NSLog(@"Mapped the article: %@", article);
	NSLog(@"Mapped the category: %@", [article.categories anyObject]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
	NSLog(@"Failed with error: %@", [error localizedDescription]);
}];
NSOperationQueue *operationQueue = [NSOperationQueue new];
[operationQueue addOperation:operation];

Map a Client Error Response to an NSError

// GET /articles/error.json returns a 422 (Unprocessable Entity)
// JSON looks like {"errors": "Some Error Has Occurred"}

// You can map errors to any class, but `RKErrorMessage` is included for free
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
// The entire value at the source key path containing the errors maps to the message
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"errorMessage"]];

NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError);
// Any response in the 4xx status code range with an "errors" key path uses this mapping
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"errors" statusCodes:statusCodes];

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://restkit.org/articles/error.json"]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[errorDescriptor]];
[operation setCompletionBlockWithSuccess:nil failure:^(RKObjectRequestOperation *operation, NSError *error) {
    // The `description` method of the class the error is mapped to is used to construct the value of the localizedDescription
	NSLog(@"Loaded this error: %@", [error localizedDescription]);

    // You can access the model object used to construct the `NSError` via the `userInfo`
    RKErrorMessage *errorMessage =  [[error.userInfo objectForKey:RKObjectMapperErrorObjectsKey] firstObject];
}];

Centralize Configuration in an Object Manager

// Set up Article and Error Response Descriptors
// Successful JSON looks like {"article": {"title": "My Article", "author": "Blake", "body": "Very cool!!"}}
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Article class]];
[mapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx
RKResponseDescriptor *articleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/articles" keyPath:@"article" statusCodes:statusCodes];

// Error JSON looks like {"errors": "Some Error Has Occurred"}
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
// The entire value at the source key path containing the errors maps to the message
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"errorMessage"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError);
// Any response in the 4xx status code range with an "errors" key path uses this mapping
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"errors" statusCodes:statusCodes];

// Add our descriptors to the manager
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[manager addResponseDescriptorsFromArray:@[ articleDescriptor, errorDescriptor ]];

[manager getObjectsAtPath:@"/articles/555.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
	// Handled with articleDescriptor
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
	// Transport error or server error handled by errorDescriptor
}];

Configure Core Data Integration with the Object Manager

NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
BOOL success = RKEnsureDirectoryExistsAtPath(RKApplicationDataDirectory(), &error);
if (! success) {
    RKLogError(@"Failed to create Application Data Directory at path '%@': %@", RKApplicationDataDirectory(), error);
}
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"Store.sqlite"];
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
if (! persistentStore) {
    RKLogError(@"Failed adding persistent store at path '%@': %@", path, error);
}
[managedObjectStore createManagedObjectContexts];

RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
manager.managedObjectStore = managedObjectStore;

Load a Collection of Objects at a Path

RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[manager getObjectsAtPath:@"/articles" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];

Manage a Queue of Object Request Operations

RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://restkit.org/articles/1234.json"]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];

[manager enqueueObjectRequestOperation:operation];
[manager cancelAllObjectRequestOperationsWithMethod:RKRequestMethodANY matchingPathPattern:@"/articles/:articleID\\.json"];

POST, PATCH, and DELETE an Object

RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[Article class]];
[responseMapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx
RKResponseDescriptor *articleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:@"/articles" keyPath:@"article" statusCodes:statusCodes];

RKObjectMapping *requestMapping = [RKObjectMapping requestMapping]; // objectClass == NSMutableDictionary
[requestMapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];

// For any object of class Article, serialize into an NSMutableDictionary using the given mapping and nest
// under the 'article' key path
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[Article class] rootKeyPath:@"article" method:RKRequestMethodAny];

RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[manager addRequestDescriptor:requestDescriptor];
[manager addResponseDescriptor:articleDescriptor];

Article *article = [Article new];
article.title = @"Introduction to RestKit";
article.body = @"This is some text.";
article.author = @"Blake";

// POST to create
[manager postObject:article path:@"/articles" parameters:nil success:nil failure:nil];

// PATCH to update
article.body = @"New Body";
[manager patchObject:article path:@"/articles/1234" parameters:nil success:nil failure:nil];

// DELETE to destroy
[manager deleteObject:article path:@"/articles/1234" parameters:nil success:nil failure:nil];

Configure Logging

// Log all HTTP traffic with request and response bodies
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);

// Log debugging info about Core Data
RKLogConfigureByName("RestKit/CoreData", RKLogLevelDebug);

// Raise logging for a block
RKLogWithLevelWhileExecutingBlock(RKLogLevelTrace, ^{
    // Do something that generates logs
});

Configure Routing

RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];

// Class Routing
[manager.router.routeSet addRoute:[RKRoute routeWithClass:[GGSegment class] pathPattern:@"/segments/:segmentID\\.json" method:RKRequestMethodGET]];

// Relationship Routing
[manager.router.routeSet addRoute:[RKRoute routeWithRelationshipName:@"amenities" objectClass:[GGAirport class] pathPattern:@"/airports/:airportID/amenities.json" method:RKRequestMethodGET]];

// Named Routes
[manager.router.routeSet addRoute:[RKRoute routeWithName:@"thumbs_down_review" resourcePathPattern:@"/reviews/:reviewID/thumbs_down" method:RKRequestMethodPOST]];

POST an Object with a File Attachment

Article *article = [Article new];
UIImage *image = [UIImage imageNamed:@"some_image.png"];

// Serialize the Article attributes then attach a file
NSMutableURLRequest *request = [[RKObjectManager sharedManager] multipartFormRequestWithObject:article method:RKRequestMethodPOST path:nil parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileData:UIImagePNGRepresentation(image)
                                name:@"article[image]"
                            fileName:@"photo.png"
                            mimeType:@"image/png"];
}];

RKObjectRequestOperation *operation = [[RKObjectManager sharedManager] objectRequestOperationWithRequest:request success:nil failure:nil];
[[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation]; // NOTE: Must be enqueued rather than started

Enqueue a Batch of Object Request Operations

RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];

Airport *jfk = [Airport new];
jfk.code = @"jfk";
Airport *lga = [Airport new];
lga.code = @"lga";
Airport *rdu = [Airport new];
rdu.code = @"rdu";

// Enqueue a GET for '/airports/jfk/weather', '/airports/lga/weather', '/airports/rdu/weather'
RKRoute *route = [RKRoute routeWithName:@"airport_weather" resourcePathPattern:@"/airports/:code/weather" method:RKRequestMethodGET];

[manager enqueueBatchOfObjectRequestOperationsWithRoute:route
                                                objects:@[ jfk, lga, rdu]
                                               progress:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
                                                   NSLog(@"Finished %d operations", numberOfFinishedOperations);
                                               } completion:^ (NSArray *operations) {
                                                   NSLog(@"All Weather Reports Loaded!");
                                               }];

Generate a Seed Database

NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
NSError *error = nil;
BOOL success = RKEnsureDirectoryExistsAtPath(RKApplicationDataDirectory(), &error);
if (! success) {
    RKLogError(@"Failed to create Application Data Directory at path '%@': %@", RKApplicationDataDirectory(), error);
}
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"Store.sqlite"];
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
if (! persistentStore) {
    RKLogError(@"Failed adding persistent store at path '%@': %@", path, error);
}
[managedObjectStore createManagedObjectContexts];

RKEntityMapping *articleMapping = [RKEntityMapping mappingForEntityForName:@"Article" inManagedObjectStore:managedObjectStore];
[articleMapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];

NSString *seedPath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"MySeedDatabase.sqlite"];
RKManagedObjectImporter *importer = [[RKManagedObjectImporter alloc] initWithManagedObjectModel:managedObjectStore.managedObjectModel storePath:seedPath];

// Import the files "articles.json" from the Main Bundle using our RKEntityMapping
// JSON looks like {"articles": [ {"title": "Article 1", "body": "Text", "author": "Blake" ]}
NSError *error;
NSBundle *mainBundle = [NSBundle mainBundle];
[importer importObjectsFromItemAtPath:[mainBundle pathForResource:@"articles" ofType:@"json"]
                          withMapping:articleMapping
                              keyPath:@"articles"
                                error:&error];

BOOL success = [importer finishImporting:&error];
if (success) {
	[importer logSeedingInfo];
}

Index and Search an Entity

NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
NSError *error = nil;
BOOL success = RKEnsureDirectoryExistsAtPath(RKApplicationDataDirectory(), &error);
if (! success) {
    RKLogError(@"Failed to create Application Data Directory at path '%@': %@", RKApplicationDataDirectory(), error);
}
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"Store.sqlite"];
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
if (! persistentStore) {
    RKLogError(@"Failed adding persistent store at path '%@': %@", path, error);
}
[managedObjectStore createManagedObjectContexts];
[managedObjectStore addSearchIndexingToEntityForName:@"Article" onAttributes:@[ @"title", @"body" ]];
[managedObjectStore addInMemoryPersistentStore:nil];
[managedObjectStore createManagedObjectContexts];
[managedObjectStore startIndexingPersistentStoreManagedObjectContext];

Article *article1 = [NSEntityDescription insertNewObjectForEntityForName:@"Article" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
article1.title = @"First Article";
article1.body = "This should match search";

Article *article2 = [NSEntityDescription insertNewObjectForEntityForName:@"Article" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
article2.title = @"Second Article";
article2.body = "Does not";

BOOL success = [managedObjectStore.mainQueueManagedObjectContext saveToPersistentStore:nil];

RKSearchPredicate *predicate = [RKSearchPredicate searchPredicateWithText:@"Match" type:NSAndPredicateType];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Article"];
fetchRequest.predicate = predicate;

// Contains article1 due to body text containing 'match'
NSArray *matches = [managedObjectStore.mainQueueManagedObjectContext executeFetchRequest:fetchRequest error:nil];
NSLog(@"Found the matching articles: %@", matches);

Unit Test a Mapping

// JSON looks like {"article": {"title": "My Article", "author": "Blake", "body": "Very cool!!"}}
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Article class]];
[mapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];

NSDictionary *article = @{ @"article": @{ @"title": @"My Title", @"body": @"The article body", @"author": @"Blake" } };
RKMappingTest *mappingTest = [[RKMappingTest alloc] initWithMapping:mapping sourceObject:article destinationObject:nil];

[mappingTest expectMappingFromKeyPath:@"title" toKeyPath:@"title" value:@"My Title"];
[mappingTest performMapping];
[mappingTest verify];

Requirements

RestKit requires iOS 8.0 and above or Mac OS X 10.9 and above.

Several third-party open source libraries are used within RestKit, including:

  1. AFNetworking - Networking Support
  2. LibComponentLogging - Logging Support
  3. SOCKit - String <-> Object Coding
  4. iso8601parser - Support for parsing and generating ISO-8601 dates

The following Cocoa frameworks must be linked into the application target for proper compilation:

  1. CFNetwork.framework on iOS
  2. CoreData.framework
  3. Security.framework
  4. MobileCoreServices.framework on iOS or CoreServices.framework on OS X

And the following linker flags must be set:

  1. -ObjC
  2. -all_load

ARC

As of version 0.20.0, RestKit has migrated the entire codebase to ARC.

If you are including the RestKit sources directly into a project that does not yet use Automatic Reference Counting, you will need to set the -fobjc-arc compiler flag on all of the RestKit source files. To do this in Xcode, go to your active target and select the "Build Phases" tab. Now select all RestKit source files, press Enter, insert -fobjc-arc and then "Done" to enable ARC for RestKit.

Serialization Formats

RestKit provides a pluggable interface for handling arbitrary serialization formats via the RKSerialization protocol and the RKMIMETypeSerialization class. Out of the box, RestKit supports handling the JSON format for serializing and deserializing object representations via the NSJSONSerialization class.

Additional Serializations

Support for additional formats and alternate serialization backends is provided via external modules that can be added to the project. Currently the following serialization implementations are available for use:

  • JSONKit
  • SBJSON
  • YAJL
  • NextiveJson
  • XMLReader + XMLWriter

Installation

The recommended approach for installing RestKit is via the CocoaPods package manager, as it provides flexible dependency management and dead simple installation. For best results, it is recommended that you install via CocoaPods >= 0.19.1 using Git >= 1.8.0 installed via Homebrew.

via CocoaPods

Install CocoaPods if not already available:

$ [sudo] gem install cocoapods
$ pod setup

Change to the directory of your Xcode project, and Create and Edit your Podfile and add RestKit:

$ cd /path/to/MyProject
$ touch Podfile
$ edit Podfile
target "YOUR PROJECT" do
	platform :ios, '7.0'
	# Or platform :osx, '10.7'
	pod 'RestKit', '~> 0.24.0'
end
# Testing and Search are optional components
pod 'RestKit/Testing', '~> 0.24.0'
pod 'RestKit/Search',  '~> 0.24.0'

Install into your project:

$ pod install

Open your project in Xcode from the .xcworkspace file (not the usual project file)

$ open MyProject.xcworkspace

Please note that if your installation fails, it may be because you are installing with a version of Git lower than CocoaPods is expecting. Please ensure that you are running Git >= 1.8.0 by executing git --version. You can get a full picture of the installation details by executing pod install --verbose.

From a Release Package or as a Git submodule

Detailed installation instructions are available in the Visual Install Guide on the Wiki.

Using RestKit in a Swift Project

Install RestKit using one of the above methods. Then add @import RestKit; (if RestKit is built as a dynamic framework) or #import <RestKit/RestKit.h> (if RestKit is built as a static library) into the bridging header for your Swift project. To enable the Core Data functionality in RestKit, add @import CoreData; into your bridging header before you import RestKit.

License

RestKit is licensed under the terms of the Apache License, version 2.0. Please see the LICENSE file for full details.

Credits

RestKit is brought to you by Blake Watters and the RestKit team.

Support is provided by the following organizations:

Comments
  • RestKit doesnt build in version 0.26

    RestKit doesnt build in version 0.26

    Maybe this is my problem, as I would assume its working for some people.

    I have updated to 0.26 today, I am using use_frameworks! in my Podfile (cocoapods 0.39)

    It fails in CoreData.h on #import <RestKit/CoreData/RKEntityMapping.h> with file not found

    I have tried cleaning, removing Pods/, no luck getting this to build.

    opened by mcfedr 115
  • RKSyncManager - monitors Core Data changes and syncs with server

    RKSyncManager - monitors Core Data changes and syncs with server

    It's taken me a long time to get back to RestKit, and I apologize for the delay. You might remember an old pull request with a clunkier implementation of this idea. This pull request is a ground-up redesign of the old idea, and includes many of the suggestions from the discussion on the aforelinked pull request.

    Basic idea: An RKSyncManager object is created automatically when an RKObjectStore is initialized. It holds onto a reference to the associated RKManagedObjectManager, and that sync manager only manages syncronization of objects registered with that objectManager and that exist in that objectStore. I.e. multiple objectManagers will have multiple syncManagers, and you can even register multiple syncManagers (for whatever reason) for the same objectManager.

    RKManagedObjectMapping is modified to have a syncMode property. This can be set to RKSyncModeNone (the default), RKSyncModeTransparent, RKSyncModeInterval, or RKSyncModeManual.

    • RKSyncModeNone - the sync manager will not track changes to objects with this syncMode.
    • RKSyncModeTransparent - the sync manager will pass all changes directly to the server if a connection is available; otherwise it archives the changes and pushes them whenever a connection becomes available.
    • RKSyncModeManual - the sync manager will only sync these objects when a call is made to one of the sync methods (on the RKSyncManager object)
    • RKSyncModeInterval - this is sort of a dummy mode for objects that will be synced on a timed interval. Its only purpose is to prevent objects with this type from being synced manually or transparently.

    The design is such that the most common use cases are very, very easy to implement, but there is still lots of flexibility and control over when and how syncing happens.

    For example, to "transparently" sync objects with a server, simply set syncMode = RKSyncModeTransparent on the object mapping, and define the routes for the object on the router. That's all - the data on the server will now always reflect what's on the iPhone and vice-versa.

    Or if you'd like to manually sync (say, when a user chooses to update), simply set the syncMode to RKSyncModeManual and define the routes for the mapping, and then call `[objectManager.syncManager sync]'

    Or if you'd like to sync objects every 60s, simply create an NSTimer that calls [objectManager.syncManager syncObjectsWithSyncMode:RKSyncModeInterval andClass:nil]

    And you can set different syncModes for different mappings, and have three different objects: one which syncs transparently, one which syncs manually, or one that syncs on an interval.

    Or if that's not enough, you have super-fine control over what gets synced with the following methods:

    - (void)syncObjectsWithSyncMode:(RKSyncMode)syncMode andClass:(Class)objectClass;
    
    - (void)pushObjectsWithSyncMode:(RKSyncMode)syncMode andClass:(Class)objectClass;
    
    - (void)pullObjectsWithSyncMode:(RKSyncMode)syncMode andClass:(Class)objectClass;
    

    In addition to a rich set of delegate callbacks defined in RKSyncManagerDelegate:

    - (void)syncManager:(RKSyncManager *)syncManager didFailSyncingWithError:(NSError*)error;
    
    - (void)syncManager:(RKSyncManager *)syncManager willSyncWithSyncMode:(RKSyncMode)syncMode andClass:(Class)objectClass;
    
    - (void)syncManager:(RKSyncManager *)syncManager didSyncWithSyncMode:(RKSyncMode)syncMode andClass:(Class)objectClass;
    
    - (void)syncManager:(RKSyncManager *)syncManager willPushObjectsInQueue:(NSArray *)queue withSyncMode:(RKSyncMode)syncMode andClass:(Class)objectClass;
    
    - (void)syncManager:(RKSyncManager *)syncManager willPullWithSyncMode:(RKSyncMode)syncMode andClass:(Class)objectClass;
    
    - (void)syncManager:(RKSyncManager *)syncManager didPushObjectsWithSyncMode:(RKSyncMode)syncMode andClass:(Class)objectClass;
    
    - (void)syncManager:(RKSyncManager *)syncManager didPullWithSyncMode:(RKSyncMode)syncMode andClass:(Class)objectClass;
    
    

    This is all up for review right now. I have written documentation (as you can see in the pull request) but it might be incomplete or unclear, and appledocs doesn't want to work for me right now, so I can't read it easily.

    I haven't yet written tests for it, because I'm still unsure of the best way to do so. I'm not sure that a thin Sinatra app will suffice, it may require a full rails app. That said, you can grab the simple app I've been using to test it here.

    Edit: Just realized I used NSLog everywhere and will update soon with RKLog functions.

    opened by ecordell 100
  • Performance Degradation in Managed Object Mapping

    Performance Degradation in Managed Object Mapping

    From the mailing list:

    I'm having similar performance issues after upgrading from 0.10 to 0.20. After playing with instruments for a bit I narrowed the issue down to this part of RKManagedObjectMappingOperationDataSource in the method mappingOperation:targetObjectForRepresentation:withMapping:inRelationship:

    // If we are mapping within a relationship, try to find an existing object without identifying attributes
        if (relationship) {
           id mutableArrayOrSetValueForExistingObjects = RKMutableCollectionValueWithObjectForKeyPath(mappingOperation.destinationObject, relationship.destinationKeyPath);
    
            NSArray *identificationAttributes = [entityMapping.identificationAttributes valueForKey:@"name"];
    
            for (NSManagedObject *existingObject in mutableArrayOrSetValueForExistingObjects) {
               if (! identificationAttributes) {
                   managedObject = existingObject;
                   [mutableArrayOrSetValueForExistingObjects removeObject:managedObject];
                   break;
               }
    
                NSDictionary *identificationAttributeValues = [existingObject dictionaryWithValuesForKeys:identificationAttributes];
    
                if ([[NSSet setWithArray:[identificationAttributeValues allValues]] isEqualToSet:[NSSet setWithObject:[NSNull null]]]) {
                   managedObject = existingObject;
                   break;
               }
           }
       }
    

    This method chews up 60% of my running time during a large mapping operation and it appears that the majority of it is spent in the above code. I am not exactly sure what the purpose of the above code is and from testing it appears that neither break statement is ever reached during any of my mapping operations. Commenting out the entire if statement gives me a significant reduction in running time.

    Can anyone provide a bit more insight as to the purpose of the above code?

    Thanks

    Performance Awaiting Verification of Fix 
    opened by blakewatters 65
  • Lean in and help to get AFNetworking 2.0 support finished.

    Lean in and help to get AFNetworking 2.0 support finished.

    Hi I know this question has been asked a dozen of times, when the AFNetworking 2.0 support for RestKit is finished. What if we all tried to lean in and help to get this job done? What is the remaining things that need to be done inorder to have a full functional RestKit with AFnetworking 2.0? Are we far from goal in current experimental branch? What thoughts and ideas need to be thought through?

    I think it could be nice if we all tried to collaborate to make this beautiful library more up to date. What are you thoughts?

    • If this is inapproriate, feel free to close this issue.
    opened by SAJK111 54
  • Crash with either `got an object reference in context (null)` or `_PFObjectIDFastHash64` error

    Crash with either `got an object reference in context (null)` or `_PFObjectIDFastHash64` error

    Working with the latest in the development branch.

    I'm posting an object question to the server with nested answer objects. While working fine on the simulator, on some devices I was experiencing an intermittent crash. Initially I was not saving the object to persistent store prior to posting. I ended up with a crash shown below:

    Serious Core Data error: requested existing object with ID 0x1da21650 <x-coredata://FBB53C8A-0B30-44B2-A056-D2FAF36DD973/TCQuestion/t247309AA-C1C4-4DF9-B136-BDBA379BDEDE288> in context <NSManagedObjectContext: 0x1dc12510>, instead got an object reference in context (null)

    Seeing this issue: https://github.com/RestKit/RestKit/issues/1208 it seemed like I might be able to resolve things by saving to persistent store first. Doing that seemed to improve the crash rate, but it would still crash the first time run on certain devices (iPhone 4), though not others (iPhone 5).

    This crash is a little uglier. Crash log below. Again, this only occurs the very first time task of posting a question occurs on the device after install. It doesn't ever seem to occur again, even after killing the application and re-launching. Seems to be similar to this issue: https://github.com/RestKit/RestKit/issues/1001

    Signal Details

    Exception Type EXC_BAD_ACCESS Code KERN_INVALID_ADDRESS at 0x120 NSManagedObjectContext Queue Crashed 0 libobjc.A.dylib objc_msgSend + 9 1 CoreData _PFObjectIDFastHash64 + 104 2 CoreFoundation CFBasicHashFindBucket + 1892 3 CoreFoundation CFDictionaryGetValue + 82 4 CoreData -[NSPersistentStoreCache incrementRefCountForObjectID:] + 24 5 CoreData -[NSSQLCore managedObjectContextDidRegisterObjectsWithIDs:] + 146 6 CoreData -[NSPersistentStoreCoordinator(_NSInternalMethods) _informAffectedStoresOfInterestByChildContextInObjectsWithObjectIDs:withSelector:] + 112 7 CoreData __95-[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidRegisterObjectsWithIDs:]_block_invoke_0 + 62 8 libdispatch.dylib _dispatch_barrier_sync_f_invoke + 30 9 CoreData _perform + 170 10 CoreData -[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidRegisterObjectsWithIDs:] + 66 11 CoreData __95-[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidRegisterObjectsWithIDs:]_block_invoke_0 + 62 12 ... libdispatch.dylib _dispatch_barrier_sync_f_slow_invoke + 84 19 UIKit UIApplicationMain + 1120 20 Three Cents
    main.m line 16 main

    The question object was inserted into the mainQueueManagedObjectContext. The question object is posted with the postObject api without anything too special. Question and Answer have their own mappings, and are connected via a relationship mapping.

    Note both crashes occur on the response, not the request (questions successfully post to the server).

    Bug Unable to Reproduce 
    opened by bobspryn 43
  • Add support for inclusion of RestKit as a Clang Module

    Add support for inclusion of RestKit as a Clang Module

    Maintains support for the use of vendored dependencies inside the main Xcode project itself, rather than using subprojects.

    @blakewatters this is necessary to support the use of RestKit as a proper framework via CocoaPods.

    opened by segiddins 41
  • Performance issues when mapping nested objects

    Performance issues when mapping nested objects

    In a project I'm on, we have recently been trying to track down some performance issues, and one of the biggest culprits has turned out to be RestKit mapping performance, particularly when mapping objects which have a bunch of nested children (and grandchildren etc.). We have one network query which returns about 500K of JSON (when formatted), with about 70 top level objects, and it is taking 3.5 - 3.8 seconds to simply do the mapping on the device. It looks like it takes about 0.1 seconds to parse the JSON into an NSDictionary, so the rest of the time is pure RestKit. While it is a somewhat substantial amount of work to do, it feels like RestKit is taking at least an order of magnitude longer than it feels like it "should". I am not using CoreData; just regular NSObjects. We are using RestKit 0.23.1. We upgraded from 0.10.x not all that long ago, but the problem query is new code, so I don't know how it would have performed using the old codebase.

    This has been noted before... #1788 is still open, and shows that a somewhat similar toolkit called EasyMapping performs about an order of magnitude faster with the same basic model, and hand-parsing was an order of magnitude faster still. While an abstract framework would obviously take more time than hand-parsing, 100x seems like a pretty stiff penalty. And while RestKit most definitely provides many more features than EasyMapping at first glance, it does feel like those features should not incur a 10x cost, particularly if not using them.

    The same issue was recently brought up in #2012, which provided a nice testing app to demonstrate the issues (which I will use), though the issue was closed. The performance seems more like a "bug" than a usage question though, so I'm adding this issue :-)

    I've done some profiling and looking through the code. There is no really obvious a-ha area that I can see... it's pretty obvious a lot of care has been taken in regards to performance, but the end result still seems lacking. It is probably going to take a number of small fixes, and maybe some internal redesign, to really improve things I fear. I have been experimenting and have some small code changes which would help... I've improved our timings so far by maybe 35-40%. It's a decent amount but still a long ways from what I was hoping for. I'll post some pull requests separately, and link them back here.

    One gut feeling is that too many objects are created during the mapping process. That, and possibly too many autorelease pools (most of them are hidden, but they are there). But I may just be misunderstanding something as well, so was hoping to discuss some possible improvements to see what the authors (and others) might think. And if anyone else has any ideas to try :-)

    A couple more notes on my data set: When I run on the simulator, it takes about 0.6 seconds, and of course mobile devices are much much slower. Since the i386 has a relatively unoptimized ObjC runtime, the retain/release thrash is a actually major part of the time. A fix which saved 20% on there (by creating many fewer temporary objects) saved only maybe 5% on the ARM device, which was kind of interesting (presumably due to tagged pointers being used for retain/release). Still, avoiding the creation of temporary objects, for code called a lot, should help performance quite a bit. The malloc and free are avoided, they never get into an autorelease pool, etc., etc. A few of my fixes are along those lines, but I think there are lots of similar places left where things could be improved that I may not have found yet. Those can be hard to pinpoint in the profiler since the associated costs can be distributed across multiple other methods (alloc one place, autorelease pool somewhere else, and dealloc in a third, etc.).

    For others looking at the thread... if your objects do not implement validateValue:forKey:, you can turn off the performsKeyValueValidation property on RKObjectMapping. That can save up to 10% of the total time. Is there any chance it makes more sense to default that to NO for non-managed-object mappings? Not a big deal since there is a way we can fix that now.

    opened by carllindberg 37
  • Fix Race Conditions in the Entity Cache

    Fix Race Conditions in the Entity Cache

    From the mailing list:

    Hey Blake, thanks to your help I was able to get to the bottom of our issue:

    1. When RestKit first creates User objects, it stores their temporary IDs in an RKEntityByAttributeCache.
    2. When a User becomes a permanent object after a save, -[MOC existingObjectWithID:] returns nil for the temporary ID.
    3. Therefore when the object is requested from the RKEntityByAttributeCache, it returns nil because -[MOC existingObjectWithID:] returned nil.
    4. Therefore when -[RKManagedObjectMappingOperationDataSource mappingOperation:targetObjectForRepresentation:withMapping:] is called during a response-mapping, it creates a duplicate User, because the cache returned nil.

    This sequence of events contains several race conditions, but I've found the problem to be very reproducible in my test case.

    My bandaid solution is to obtain a permanent ID in -[RKEntityCache addObject:], but ideally we would obtain permanent IDs for all inserted objects in one swoop, prior to putting their object IDs in the cache.

    Bug 
    opened by blakewatters 37
  • Saving new object from child context results in EXC_BAD_ACCESS (development branch)

    Saving new object from child context results in EXC_BAD_ACCESS (development branch)

    I have child managed object context created with RestKit's helpers, within that child context I've instantiated a new model instance. When I save that object (using RKObjectManager#postObject...) the application crashes. The thread causing the crashes always has a backtrace looking like this:

    Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
    Exception Codes: KERN_INVALID_ADDRESS at 0x0000000e
    Crashed Thread:  0
    
    Thread 0 name:  Dispatch queue: NSManagedObjectContext Queue
    Thread 0 Crashed:
    0   libobjc.A.dylib                 0x330bff72 objc_msgSend + 10
    1   CoreData                        0x31dbad30 _PFObjectIDFastHash64 + 100
    2   CoreFoundation                  0x37d599c8 __CFDictionaryHashKey + 12
    3   CoreFoundation                  0x37cdc848 CFBasicHashFindBucket + 1780
    4   CoreFoundation                  0x37cdc13e CFDictionaryGetValue + 110
    5   CoreData                        0x31e3b4ae -[NSPersistentStoreCache incrementRefCountForObjectID:] + 18
    6   CoreData                        0x31e5ece4 -[NSSQLCore managedObjectContextDidRegisterObjectsWithIDs:] + 124
    7   CoreData                        0x31dc23a4 -[NSPersistentStoreCoordinator(_NSInternalMethods) _informAffectedStoresOfInterestByChildContextInObjectsWithObjectIDs:withSelector:] + 76
    8   CoreData                        0x31e18350 __-[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidRegisterObjectsWithIDs:]_block_invoke_1 + 64
    9   CoreData                        0x31e105b4 internalBlockToNSManagedObjectContextPerform + 4
    10  libdispatch.dylib               0x346be7e0 _dispatch_barrier_sync_f_invoke + 20
    11  libdispatch.dylib               0x346be640 dispatch_barrier_sync_f$VARIANT$mp + 56
    12  libdispatch.dylib               0x346be260 dispatch_sync_f$VARIANT$mp + 12
    13  CoreData                        0x31e1e55e _perform + 154
    14  CoreData                        0x31e1e7cc -[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidRegisterObjectsWithIDs:] + 64
    15  CoreData                        0x31e18350 __-[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidRegisterObjectsWithIDs:]_block_invoke_1 + 64
    16  CoreData                        0x31e105b4 internalBlockToNSManagedObjectContextPerform + 4
    17  libdispatch.dylib               0x346bfb80 _dispatch_barrier_sync_f_slow_invoke + 76
    18  libdispatch.dylib               0x346beee0 _dispatch_main_queue_callback_4CF$VARIANT$mp + 188
    19  CoreFoundation                  0x37d672a6 __CFRunLoopRun + 1262
    20  CoreFoundation                  0x37cea49e CFRunLoopRunSpecific + 294
    21  CoreFoundation                  0x37cea366 CFRunLoopRunInMode + 98
    22  GraphicsServices                0x361cd432 GSEventRunModal + 130
    23  UIKit                           0x30b9bcce UIApplicationMain + 1074
    24  GlobalDriver2ClientBooking      0x000d8fae main (main.m:8)
    25  GlobalDriver2ClientBooking      0x000d8f48 start + 32
    

    and the thread that seems likely to be generating the even that causes it looks like this:

    Thread 7 name:  Dispatch queue: NSManagedObjectContext Queue
    Thread 7:
    0   libsystem_kernel.dylib          0x309e5054 semaphore_wait_trap + 8
    1   libdispatch.dylib               0x346c04ee _dispatch_thread_semaphore_wait$VARIANT$mp + 6
    2   libdispatch.dylib               0x346be69e _dispatch_barrier_sync_f_slow + 86
    3   libdispatch.dylib               0x346be618 dispatch_barrier_sync_f$VARIANT$mp + 16
    4   libdispatch.dylib               0x346be260 dispatch_sync_f$VARIANT$mp + 12
    5   CoreData                        0x31e1e55e _perform + 154
    6   CoreData                        0x31e1e7cc -[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidRegisterObjectsWithIDs:] + 64
    7   CoreData                        0x31dbf642 _PFFaultHandlerLookupRow + 1434
    8   CoreData                        0x31dbed54 _PF_FulfillDeferredFault + 188
    9   CoreData                        0x31e0dfc2 _PF_Handler_WillAccess_Property + 34
    10  CoreData                        0x31e0dabe _PF_ManagedObject_WillChangeValueForKeyIndex + 58
    11  CoreData                        0x31e0e4ec _sharedIMPL_setvfk_core + 104
    12  CoreData                        0x31e1037e -[NSManagedObject(_PFDynamicAccessorsAndPropertySupport) _setGenericValue:forKey:withIndex:flags:] + 26
    13  CoreData                        0x31e0862a _PF_Handler_Public_SetProperty + 46
    14  CoreData                        0x31e087ce -[NSManagedObject(_NSInternalMethods) _maintainInverseRelationship:forProperty:oldDestination:newDestination:] + 242
    15  CoreData                        0x31e07d7c -[NSManagedObject(_NSInternalMethods) _maintainInverseRelationship:forProperty:forChange:onSet:] + 820
    16  CoreData                        0x31e0842a -[NSManagedObject(_NSInternalMethods) _didChangeValue:forRelationship:named:withInverse:] + 1582
    17  CoreData                        0x31e1516a -[NSManagedObjectContext observeValueForKeyPath:ofObject:change:context:] + 322
    18  Foundation                      0x36f41138 NSKeyValueNotifyObserver + 252
    19  Foundation                      0x36f40d9e NSKeyValueDidChange + 318
    20  Foundation                      0x36f653d4 -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:withSetMutation:usingObjects:] + 88
    21  CoreData                        0x31e04704 -[NSManagedObject didChangeValueForKey:withSetMutation:usingObjects:] + 56
    22  CoreData                        0x31dd39e4 -[_NSNotifyingWrapperMutableSet setSet:] + 120
    23  GlobalDriver2ClientBooking      0x00197b32 -[RKMappingOperation applyRelationshipMappings] (RKMappingOperation.m:541)
    24  GlobalDriver2ClientBooking      0x001996e4 -[RKMappingOperation main] (RKMappingOperation.m:638)
    25  Foundation                      0x36f4038c -[__NSOperationInternal start] + 856
    26  GlobalDriver2ClientBooking      0x0018efc8 -[RKMapperOperation mapFromObject:toObject:atKeyPath:usingMapping:] (RKMapperOperation.m:219)
    27  GlobalDriver2ClientBooking      0x0018e248 -[RKMapperOperation mapObject:atKeyPath:usingMapping:] (RKMapperOperation.m:147)
    28  GlobalDriver2ClientBooking      0x0018f9a8 -[RKMapperOperation performMappingForObject:atKeyPath:usingMapping:] (RKMapperOperation.m:268)
    29  GlobalDriver2ClientBooking      0x0018ff50 -[RKMapperOperation performKeyPathMappingUsingMappingDictionary:] (RKMapperOperation.m:308)
    30  GlobalDriver2ClientBooking      0x001903e0 -[RKMapperOperation main] (RKMapperOperation.m:333)
    31  Foundation                      0x36f4038c -[__NSOperationInternal start] + 856
    32  GlobalDriver2ClientBooking      0x0016d0a6 __73-[RKManagedObjectResponseMapperOperation performMappingWithObject:error:]_block_invoke_0 (RKResponseMapperOperation.m:262)
    33  CoreData                        0x31e1e3e8 developerSubmittedBlockToNSManagedObjectContextPerform + 68
    34  libdispatch.dylib               0x346be7e0 _dispatch_barrier_sync_f_invoke + 20
    35  libdispatch.dylib               0x346be640 dispatch_barrier_sync_f$VARIANT$mp + 56
    36  libdispatch.dylib               0x346be260 dispatch_sync_f$VARIANT$mp + 12
    37  CoreData                        0x31e11904 -[NSManagedObjectContext performBlockAndWait:] + 160
    38  GlobalDriver2ClientBooking      0x0016c7fe -[RKManagedObjectResponseMapperOperation performMappingWithObject:error:] (RKResponseMapperOperation.m:231)
    39  GlobalDriver2ClientBooking      0x0016bbe6 -[RKResponseMapperOperation main] (RKResponseMapperOperation.m:181)
    40  Foundation                      0x36f4038c -[__NSOperationInternal start] + 856
    41  GlobalDriver2ClientBooking      0x0015ed0e -[RKManagedObjectRequestOperation performMappingOnResponse:] (RKManagedObjectRequestOperation.m:98)
    42  GlobalDriver2ClientBooking      0x00169330 -[RKObjectRequestOperation main] (RKObjectRequestOperation.m:196)
    43  Foundation                      0x36f4038c -[__NSOperationInternal start] + 856
    44  Foundation                      0x36fa978c __block_global_6 + 96
    45  libdispatch.dylib               0x346bcc52 _dispatch_call_block_and_release + 6
    46  libdispatch.dylib               0x346bf810 _dispatch_worker_thread2 + 252
    47  libsystem_c.dylib               0x32f41df4 _pthread_wqthread + 288
    48  libsystem_c.dylib               0x32f41cc8 start_wqthread + 0
    

    It's possible that it's a bug in CoreData, but it'd be harder to prove/determine that. Also, in the debugging process I added code to ensure that I didn't have any KVO listeners or fetch request controllers outstanding on the original object. That would seem to suggest that it's not a bug in how I'm using it.

    opened by jcoleman 37
  • How to map attribute from relationship as identification attribute

    How to map attribute from relationship as identification attribute

    Hello, If I have a Person entity who has a to-many relationship of Field entities, can I somehow use Person.id as an identification attribute for each Field? It would be easy enough to set up metadata mapping for the case where I was pulling one person at a time, but given an array of people, each having an array of fields, I'm not sure how I can set up the Field mapping to reference the person's ID. Each Field can be exactly identified by it's type plus the related person's id.

    The issue is that RestKit's mapper is grabbing random Field objects from Core Data and overwriting them with the downloaded data, and sometimes that includes a Field that belongs to a different Person. I could get rid of identification attributes completely, but then I'd lose the other local-only data I was storing on the Fields (stuff not being downloaded from the server).

    I tried adding an identification attribute to the Field of Person.id, but that didn't work. My other thought was somehow mapping the person ID field onto the Field directly, but it is only available above the level that Field mapping is happening:

    {
        "person": {
            "id": 1,
            "fields": [
                {
                    "type": "name",
                    "value": "Tommy"
                }
            ]
        }
    }
    

    is there a way to reference keys above the current mapping's key path?

    Thanks!

    Feature 
    opened by airdrummingfool 34
  • Use explicit `userInfo` keys for `NSManagedObjectContextDidSaveNotification`

    Use explicit `userInfo` keys for `NSManagedObjectContextDidSaveNotification`

    In iOS 10 beta 4 there is a new key in the userInfo dictionary, managedObjectContext, so the existing collection operator causes a crash as it assumes all values are NSSets.

    I have added explicit checking for inserted, deleted and updated objects.

    iOS 10 
    opened by alexanderedge 29
  • Xcode 12.5 / Xcode 13 Issues

    Xcode 12.5 / Xcode 13 Issues

    Hello I have App which use RestKit. Until around Xcode 12.3 App works well. But now with Xcode 12.5 and also Xcode 13, App don't fire any request to our backend and there is no network response of course.

    I can't prove 100% it's RestKit Library is reason for this but most probably it is.

    Someone has similar Issues?

    opened by phr85 0
  • App Crash , Xcode 12.5 this class is not key value coding-compliant for the key

    App Crash , Xcode 12.5 this class is not key value coding-compliant for the key

    Issue: Native ios swift app crash in Xcode 12.5.

    Reason : When MKMapperOperation tries to map attribute value it throws an exception :

    Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<RestKitExample.xx0x600002d463e0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key token.'

    It was working fine with code 11.xx.

    Screenshot 2021-06-07 at 2 46 43 PM
    opened by IshaqiOS 2
  • [RKObjectMapping .cxx_destruct]

    [RKObjectMapping .cxx_destruct]

    Crashed: com.apple.main-thread 0 libsystem_platform.dylib 0x1bd71a074 _os_unfair_lock_corruption_abort + 36 1 libsystem_platform.dylib 0x1bd71b38c _os_unfair_lock_lock_slow + 288 2 CoreFoundation 0x1bdb32588 _cow_release + 44 3 CoreFoundation 0x1bd9f83b4 -[__NSArrayM dealloc] + 52 4 libobjc.A.dylib 0x1bcce57cc object_cxxDestructFromClass(objc_object*, objc_class*) + 148 5 libobjc.A.dylib 0x1bccf56b8 objc_destructInstance + 68 6 libobjc.A.dylib 0x1bccf5720 object_dispose + 16 7 Connect 0x1009f1c98 -[RKCompoundValueTransformer dealloc] + 711 (RKValueTransformers.m:711) 8 Connect 0x1009dee84 -[RKObjectMapping .cxx_destruct] + 113 (RKObjectMapping.m:113) 9 libobjc.A.dylib 0x1bcce57cc object_cxxDestructFromClass(objc_object*, objc_class*) + 148 10 libobjc.A.dylib 0x1bccf56b8 objc_destructInstance + 68 11 libobjc.A.dylib 0x1bccf5720 object_dispose + 16 12 Connect 0x100942bcc __destroy_helper_block_e8_32s40s + 368 (LKAddOnController.m:368) 13 libsystem_blocks.dylib 0x1bd5a7a44 _Block_release + 152 14 libsystem_blocks.dylib 0x1bd5a7a44 _Block_release + 152 15 Connect 0x100966a1c __destroy_helper_block_e8_32s40s48s56s + 678 (LKDataClient.m:678) 16 libsystem_blocks.dylib 0x1bd5a7a44 _Block_release + 152 17 Connect 0x100942bcc __destroy_helper_block_e8_32s40s + 368 (LKAddOnController.m:368) 18 libsystem_blocks.dylib 0x1bd5a7a44 _Block_release + 152 19 CoreFoundation 0x1bd9fac24 -[__NSArrayM removeAllObjects] + 264 20 Connect 0x100ef75ec -[BFTask runContinuations] + 309 (BFTask.m:309) 21 Connect 0x100ef7240 -[BFTask trySetError:] + 266 (BFTask.m:266) 22 Connect 0x100ef85c8 -[BFTaskCompletionSource setError:] + 52 (BFTaskCompletionSource.m:52) 23 Connect 0x100983c30 __39+[LKNetworkSessionManager sendRequest:]_block_invoke_2.241 + 236 (LKNetworkSessionManager.m:236) 24 Connect 0x100ec3da8 __116-[AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:uploadProgress:downloadProgress:success:failure:]_block_invoke_2 + 301 (AFHTTPSessionManager.m:301) 25 Connect 0x100ed2068 __72-[AFURLSessionManagerTaskDelegate URLSession:task:didCompleteWithError:]_block_invoke_2.104 + 248 (AFURLSessionManager.m:248) 26 libdispatch.dylib 0x1bd54ba38 _dispatch_call_block_and_release + 24 27 libdispatch.dylib 0x1bd54c7d4 _dispatch_client_callout + 16 28 libdispatch.dylib 0x1bd4f9e50 _dispatch_main_queue_callback_4CF$VARIANT$mp + 628 29 CoreFoundation 0x1bda9fb20 CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE + 12 30 CoreFoundation 0x1bda9aa58 __CFRunLoopRun + 1924 31 CoreFoundation 0x1bda99fb4 CFRunLoopRunSpecific + 436 32 GraphicsServices 0x1bfc9b79c GSEventRunModal + 104 33 UIKitCore 0x1e9d77c38 UIApplicationMain + 212 34 Connect 0x1009fa10c main + 4301037836 (:4301037836) 35 libdyld.dylib 0x1bd55d8e0 start + 4

    opened by Rajeev09 0
  • Mapping boolean response

    Mapping boolean response

    Hello!

    My API returns a boolean response (simply true or false). I wonder what is the correct way to map such a response using "responseDescriptorWithMapping" method?

    Thank you!

    opened by tolik85 0
Releases(v0.27.2)
  • v0.27.2(Jul 19, 2017)

  • v0.27.1(Jul 3, 2017)

    This release includes a major migration of the project in order to support Xcode 8. Many of the internal dependencies have been updated and Travis-CI builds are finally fully operational again.

    Also, this release includes a major bug fix related to iOS 10.x:

    • #2449: Use explicit userInfo keys for NSManagedObjectContextDidSaveNotification
    Source code(tar.gz)
    Source code(zip)
  • v0.27.0(Jul 26, 2016)

    From #2434:

    • Removed iOS 5 related code in RKPathUtilities.m
    • Increased deployment target to iOS 8.0 and OS X 10.9 on both project and test apps
    • Updated rakefile: fixed build:examples task
    • ~~Allowed warnings on pod lib lint (due to AFNetworking)~~
    • Fixed AFNetworking reachability issue with Cocoapods use_frameworks!
    • Fixed headers not found issue with Cocoapods > 0.38.2
    • Moved RKHTTPUtilities into Network directory
    • Updated example projects pod files
    • Removed AFNetworking dependency from podspec
    • Renamed all AFNetworking classes to AFRK to be able to install any version of AFNetworking meanwhile using RestKit.
    Source code(tar.gz)
    Source code(zip)
  • v0.24.1(Apr 3, 2015)

  • v0.24.0(Nov 22, 2014)

    This release focuses on some major performance improvements contributed by @carllindberg, as well as enforcing stricter compliance with CoreData's thread confinement model.

    This release also sees the minimum supported iOS version being increased to 5.1.1.

    Source code(tar.gz)
    Source code(zip)
  • v0.23.3(Aug 19, 2014)

    Maintenance

    This is a small maintenance update that focuses on several crucial improvements to core RestKit functionality, in addition to incremental improvements on the modularization front. The RestKit Core team welcomes Valerio Mazzeo, who was the driving force behind this release.

    Changelog

    • Fix equivalence tests for request and response descriptors Alex Leigh
    • Provide a single entry point for retrieving the fetch requests from the fetch request blocks Valerio Mazzeo #1995
    • Implemented indexing on NSArray of NSString and NSNumber Valerio Mazzeo
    • Allow for the Testing and CoreData subspecs without the Search subspec Samuel E. Giddins #1987
    • Extended RKObjectMappingMatcher capabilities with a RKKeyPathClassObjectMappingMatcher class Valerio Mazzeo
    Source code(tar.gz)
    Source code(zip)
  • v0.23.2(Jul 17, 2014)

    Maintenance

    This is a maintenance release that brings incremental updates to modularization and various facets of the RestKit architecture.

    Changelog

    • Honor passed in sqlite options when creating persistent store
    • Make more functions work in .mm files Romain Criton
    • Fix RKMappingOperation skipping validation when data source tells it to set unchanged values Coneko
    • Prefer the use RKAttributeMapping value transformers if provided Kamil Kocemba
    • Copy RKObjectMapping. sourceToDestintationKeyTransformationBlock Ian G
    • Make RestKit.h importable with stand-alone subspecs Samuel Giddins
    • Add rudimentary dynamic mapping equivalence Jason Peebles
    • Switch to a vendored SOCKit version for manual installation
    • Memoization of RKResponseDescriptor's path matcher Karl Gluck
    • Removed hidden Support dependency upon AFNetworking
    Source code(tar.gz)
    Source code(zip)
  • v0.23.1(Apr 24, 2014)

    Modernization & Maintenance

    This release updates RestKit to fix warnings under Xcode 5.1 and transitions off of deprecated technologies such as XCTest.

    Changelog

    • Replaced numerous uses of NSAssert with NSException where appropriate
    • Update project to build for arm64 on iOS targets Matt Magoffin #1677
    • Improved handling for response codes with optional bodies #1686
    • Prevented deletion of managed objects if a response mapper error is encountered Konstantin Novikov #1695
    • Improved checking around Etags #1599
    • Ensured MOC isn't saved when an error is mapped
    • Set proper error in RKMappingOperation Ian G
    • Use custom date formatter on attribute mapping when available Freddie Tilley
    • Allowed each subspec to be used standalone Samuel E. Giddins #1770
    Source code(tar.gz)
    Source code(zip)
  • v0.23.0(Apr 23, 2014)

  • v0.22.0(Aug 16, 2014)

  • v0.20.3(Aug 20, 2013)

    Released: July 12, 2013
    Install via CocoaPods:

    pod 'RestKit', '~> 0.20.0'
    

    We are very pleased to announce the immediate availability of RestKit 0.20.3. This was a quick release that focused on fixing several high priority bugs and introduced several new feature enhancements in the network layer.

    Release Details

    The full details of all features and fixes present in the release are available on Github…

    Release Highlights

    The 0.20.3 release contains a blend of bug fixes and feature enhancements. Highlights of the release include:

    • Improvements to the modificationAttribute logic. A modification attribute can be designated on an RKEntityMapping to accelerate mapping of large payloads by intelligently detecting changes on a per object basis. (Issue #1391)
    • Fixed memory leaks in RKOperationStateMachine. (Issue #1404)
    • Added support for mapping the @parent and @root pseudo-key-paths. This enhancement provides for upward traversal of representations at mapping time, greatly enhancing mapping flexibility. Big thanks to @percysnoodle on this one. (Issue #1435)
    • Added support for custom data source implementations in the network layer. (Issue #1442)
    • Added support for using RKRequestMethod as a bitmask in routing. (Issue #1476)
    • Added support for using RKReqeustMethod bitmask values in RKRequestDescriptor and RKResponseDescriptor. (Issue #1482)
    • Added support for intelligently mapping additional objects in a payload by eliminating reliance on targetObject in RKMapperOperation. (Issue #1309)

    Contributors

    A special thanks to these contributors during the 0.20.3 release:

    • @segiddins
    • @flambert
    • @valeriomazzeo
    • @percysnoodle
    • @sixten
    • @dulaccc
    Source code(tar.gz)
    Source code(zip)
    RestKit-0.20.3.zip(16.42 MB)
Owner
The RestKit Project
The RestKit Project
OctopusKit is a simplicity but graceful solution for invoke RESTful web service APIs

OctopusKit OctopusKit is a simplicity but graceful solution for invoke RESTful web service APIs,it can help coder develop app based MVC pattern, it ca

i ⚒  kit 3 Jul 29, 2021
A Swift web framework and HTTP server.

A Swift Web Framework and HTTP Server Summary Kitura is a web framework and web server that is created for web services written in Swift. For more inf

Kitura 7.6k Jan 6, 2023
A Ruby on Rails inspired Web Framework for Swift that runs on Linux and OS X

IMPORTANT! We don't see any way how to make web development as great as Ruby on Rails or Django with a very static nature of current Swift. We hope th

Saulius Grigaitis 2k Dec 5, 2022
A minimal, fast and unopinionated web framework for Swift

![Fire Image] (http://i.imgur.com/1qR6Nl4.png) Blackfire An extremely fast Swift web framework ?? Getting Started If you're familiar with express.js t

Elliott Minns 908 Dec 2, 2022
A Swift Multiplatform Single-threaded Non-blocking Web and Networking Framework

Serverside non-blocking IO in Swift Ask questions in our Slack channel! Lightning (formerly Edge) Node Lightning is an HTTP Server and TCP Client/Serv

SkyLab 316 Oct 6, 2022
Minimal web framework and middleware for Swift

Kunugi Kunugi(椚) is minimal web framework and middleware systems for Swift. This is inpired by Node.js' Koa. Kunugi doesn't provide http server its se

Yusuke Ito 35 Apr 18, 2022
💧 A server-side Swift web framework.

Vapor is a web framework for Swift. It provides a beautifully expressive and easy to use foundation for your next website, API, or cloud project. Take

Vapor 22.4k Jan 2, 2023
Super lightweight web framework in Swift based on SWSGI

Ambassador Super lightweight web framework in Swift based on SWSGI Features Super lightweight Easy to use, designed for UI automatic testing API mocki

Envoy 170 Nov 15, 2022
libuv base Swift web HTTP server framework

Notice Trevi now open a Trevi Community. Yoseob/Trevi project split up into respective Trevi, lime, middlewares and sys packages at our community. If

leeyoseob 46 Jan 29, 2022
This generic SOAP client allows you to access web services using a your iOS app, Mac OS X app and AppleTV app.

This generic SOAP client allows you to access web services using a your iOS app, Mac OS X app and Apple TV app. With this Framework you can create iPh

Prioregroup.com 479 Nov 22, 2022
WKZombie is an iOS/OSX web-browser without a graphical user interface.

WKZombie is a Swift framework for iOS/OSX to navigate within websites and collect data without the need of User Interface or API, also known as Headless browser. It can be used to run automated tests / snapshots and manipulate websites using Javascript.

Mathias Köhnke 1.1k Dec 16, 2022
Lightweight library for web server applications in Swift on macOS and Linux powered by coroutines.

Why Zewo? • Support • Community • Contributing Zewo Zewo is a lightweight library for web applications in Swift. What sets Zewo apart? Zewo is not a w

Zewo 1.9k Dec 22, 2022
Robust Swift networking for web APIs

Conduit Conduit is a session-based Swift HTTP networking and auth library. Within each session, requests are sent through a serial pipeline before bei

Mindbody 52 Oct 26, 2022
A lightweight library for writing HTTP web servers with Swift

Taylor Disclaimer: Not actively working on it anymore. You can check out some alternatives Swift 2.0 required. Working with Xcode 7.1. Disclaimer: It

Jorge Izquierdo 925 Nov 17, 2022
Swift Express is a simple, yet unopinionated web application server written in Swift

Documentation <h5 align="right"><a href="http://demo.swiftexpress.io/">Live ?? server running Demo <img src="https://cdn0.iconfinder.com/data/icons/

Crossroad Labs 850 Dec 2, 2022
Frank is a DSL for quickly writing web applications in Swift

Frank Frank is a DSL for quickly writing web applications in Swift with type-safe path routing. Sources/main.swift import Frank // Handle GET request

Kyle Fuller Archive 377 Jun 29, 2022
High Performance (nearly)100% Swift Web server supporting dynamic content.

Dynamo - Dynamic Swift Web Server Starting this project the intention was to code the simplest possible Web Server entirely in Swift. Unfortunately I

John Holdsworth 68 Jul 25, 2022
MVVM project to show AQI of cities via web socket

Air Quality Monitoring Application Swift project with JSON parsing using codable About the application The app consists of live realtime data from the

Pran Kishore 0 Nov 27, 2021
a NSURLCache subclass for handling all web requests that use NSURLRequest

EVURLCache What is this? This is a NSURLCache subclass for handeling all web requests that use NSURLRequest. (This includes UIWebView) The EVURLCache

Edwin Vermeer 296 Dec 18, 2022