RestKit 是一個用于更好支持RESTful風格服務器接口的iOS庫,可直接將聯網獲取的json/xml數據轉換為iOS對象.
pod 'RestKit'# 測試和搜索是可選的組件pod 'RestKit/Testing'pod 'RestKit/Search'
在需要的地方,引入頭文件:
/* 如果使用CoreData,一定要在引入RestKit前引入CoreData.RestKit中有一些預編譯宏是基于CoreData是否已經引入;不提前引入CoreData,RestKit中CoreData相關的功能就無法正常使用. */#import <CoreData/CoreData.h>#import <RestKit/RestKit.h>/* Testing 和 Search 是可選的. */#import <RestKit/Testing.h>#import <RestKit/Search.h>
以下示例展示了RestKit的基本用法,涉及到網絡請求的部分已轉由iOS122的測試服務器提供模擬數據.示例代碼復制到Xcode中,可直接執行.建議自己新建工程,通過CocoaPods安裝RestKit測試.
/** * 定義數據模型: Article */@interface Article : NSObject@PRoperty (nonatomic, copy) NSString * title;@property (nonatomic, copy) NSString * author;@property (nonatomic, copy) NSString * body;@end
// 從/vitural/articles/1234.json獲取一篇文章的信息,并把它映射到一個數據模型對象中.// JSON 內容: {"article": {"title": "My Article", "author": "Blake", "body": "Very cool!!"}}RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Article class]];[mapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // 任何 2xx 狀態.RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/vitural/articles/:articleID" keyPath:@"article" statusCodes:statusCodes]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://dev-test.ios122.com/vitural/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];
/* 需要額外引入頭文件:#import "RKManagedObjectRequestOperation.h". */ // 從 /vitural/articles/888.json 獲取文章和文章標簽,并存放到Core Data實體中.// JSON 數據類似: {"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);} // 如果改了實體結構,注意刪除手機或模擬器對應路徑的數據庫// 文章和標簽,要設置 1 對 多的關聯! NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"RestKit.sqlite"]; // 此處要和自己的CoreData數據庫的名字一致.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]; /* 要在Core Data中預定義相關實體. */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); // 任何 2xx的狀態碼RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:articleMapping method:RKRequestMethodAny pathPattern:@"/vitural/articles/:articleID" keyPath:@"article" statusCodes:statusCodes]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://dev-test.ios122.com/vitural/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) { NSLog(@"Mapped the article: %@", [result firstObject]); } failure:^(RKObjectRequestOperation *operation, NSError *error) { NSLog(@"Failed with error: %@", [error localizedDescription]);}];NSOperationQueue *operationQueue = [NSOperationQueue new];[operationQueue addOperation:operation];
// 獲取 /vitural/articles/error.json,返回報頭 422 (Unprocessable Entity)// JSON 內容: {"errors": "Some Error Has Occurred"}// 你可以將錯誤映射到任何類,但是通常使用`RKErrorMessage`就夠了.RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];// 包含錯誤信息的鍵對應的值,映射到iOS類的錯誤信息相關的屬性中.[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"errorMessage"]];NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError);// 任意報頭狀態碼為 4xx 的返回值.RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"errors" statusCodes:statusCodes];NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://dev-test.ios122.com/vitural/articles/error.json"]];RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@ [errorDescriptor]];[operation setCompletionBlockWithSuccess:nil failure:^(RKObjectRequestOperation *operation, NSError *error) { // 映射到的iOS錯誤類的`description`方法用來作為localizedDescription的值 NSLog(@"Loaded this error: %@", [error localizedDescription]); // 你可以通過`NSError`的`userInfo`獲取映射后的iOS類的對象. RKErrorMessage *errorMessage = [[error.userInfo objectForKey:RKObjectMapperErrorObjectsKey] firstObject]; NSLog(@"%@", errorMessage);}];[operation start];
// 設置文章或請求出錯時的響應描述.// 成功時的JSON類似于: {"article": {"title": "My Article", "author": "Blake", "body": "Very cool!!"}}RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Article class]];[mapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // 任意 2xx 狀態碼.RKResponseDescriptor *articleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/vitural/articles/:articleID" keyPath:@"article" statusCodes:statusCodes];// 出錯時返回的JSON類似: {"errors": "Some Error Has Occurred"}RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];// 包含錯誤信息的鍵對應的值,映射到iOS類的錯誤信息相關的屬性中.[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"errorMessage"]];NSIndexSet *errorStatusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError);// 任意報頭狀態碼為 4xx 的返回值.RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"errors" statusCodes:errorStatusCodes];// 把響應描述添加到管理器上.RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://dev-test.ios122.com"]];[manager addResponseDescriptorsFromArray:@[articleDescriptor, errorDescriptor ]];// 注意,此處所用的接口已在服務器端設置為隨機返回正確或錯誤的信息,以便于測試.[manager getObject: nil path:@"/vitural/articles/555.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { // 處理請求成功獲取的文章. Article *article = [mappingResult firstObject]; NSLog(@"Mapped the article: %@", article);} failure:^(RKObjectRequestOperation *operation, NSError *error) { // 處理錯誤信息. NSLog(@"%@", error.localizedDescription);}];
/* 配置管理器. */RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://dev-test.ios122.com"]];[RKObjectManager setSharedManager: manager]; /* 將管理器與CoreData整合到一起. */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:@"RestKit.sqlite"]; // 此處要和自己的CoreData數據庫的名字一致.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]; manager.managedObjectStore = managedObjectStore; /* 將網絡請求的數據存儲到CoreData, 要在Core Data中預定義相關實體. */RKEntityMapping *categoryMapping = [RKEntityMapping mappingForEntityForName:@"Category" inManagedObjectStore:manager.managedObjectStore];[categoryMapping addAttributeMappingsFromDictionary:@{ @"id": @"categoryID", @"name": @"name" }];RKEntityMapping *articleMapping = [RKEntityMapping mappingForEntityForName:@"Article" inManagedObjectStore:manager.managedObjectStore];[articleMapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];[articleMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"categories" toKeyPath:@"categories" withMapping:categoryMapping]]; NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // 任何 2xx的狀態碼RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:articleMapping method:RKRequestMethodAny pathPattern:@"/vitural/articles/:articleID" keyPath:@"article" statusCodes:statusCodes]; [manager addResponseDescriptor: responseDescriptor];[manager getObject: nil path:@"/vitural/articles/888.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { // 處理請求成功獲取的文章. NSLog(@"Mapped the article: %@", [mappingResult firstObject]);} failure:^(RKObjectRequestOperation *operation, NSError *error) { // 處理錯誤信息. NSLog(@"%@", error.localizedDescription);}];
// 設置文章或請求出錯時的響應描述. // 成功時的JSON類似于: [{"article":{"title":"My Article 1","author":"Blake 1","body":"Very cool!! 1"}},{"article":{"title":"My Article 2","author":"Blake 2","body":"Very cool!! 2"}},{"article":{"title":"My Article 3","author":"Blake 3","body":"Very cool!! 3"}},{"article":{"title":"My Article 4","author":"Blake 4","body":"Very cool!! 4"}}] RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Article class]]; [mapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]]; NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // 任意 2xx 狀態碼. RKResponseDescriptor *articleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/vitural/articles" keyPath:@"article" statusCodes:statusCodes]; // 出錯時返回的JSON類似: {"errors": "Some Error Has Occurred"} RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]]; // 包含錯誤信息的鍵對應的值,映射到iOS類的錯誤信息相關的屬性中. [errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"errorMessage"]]; NSIndexSet *errorStatusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError); // 任意報頭狀態碼為 4xx 的返回值. RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"errors" statusCodes:errorStatusCodes]; // 把響應描述添加到管理器上. RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://dev-test.ios122.com"]]; [manager addResponseDescriptorsFromArray:@[articleDescriptor, errorDescriptor ]]; [manager getObjectsAtPath:@"/vitural/articles" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { // 處理請求成功獲取的文章. NSArray * articles = [mappingResult array]; [articles enumerateObjectsUsingBlock:^(Article * article, NSUInteger idx, BOOL *stop) { NSLog(@"Mapped the article: %@", article); }]; } failure:^(RKObjectRequestOperation *operation, NSError *error) { // 處理錯誤信息. NSLog(@"%@", error.localizedDescription); }];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://dev-test.ios122.com"]];NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://dev-test.ios122.com/vitural/articles/1234.json"]]; RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Article class]]; [mapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]]; NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // 任意 2xx 狀態碼. RKResponseDescriptor *articleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/vitural/articles/1234.json" keyPath:@"article" statusCodes:statusCodes];RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[articleDescriptor]];[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]);}];[manager enqueueObjectRequestOperation:operation]; // 有了這句,就不需要再調用[operation start] 來發起請求了.[manager cancelAllObjectRequestOperationsWithMethod:RKRequestMethodAny matchingPathPattern:@"/vitural/articles/:articleID//.json"];
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[Article class]];[responseMapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // 任何 2xx 狀態碼RKResponseDescriptor *articlesDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:@"/vitural/articles" keyPath:@"article" statusCodes:statusCodes];RKResponseDescriptor *articleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:@"/vitural/articles/:id" keyPath:@"article" statusCodes:statusCodes];RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];[requestMapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];// 將 Article 序列化為NSMutableDictionary ,并以 `article`為鍵.RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[Article class] rootKeyPath:@"article" method:RKRequestMethodAny];RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://dev-test.ios122.com"]];[manager addRequestDescriptor:requestDescriptor];[manager addResponseDescriptor:articlesDescriptor];[manager addResponseDescriptor:articleDescriptor];Article *article = [Article new];article.title = @"Introduction to RestKit";article.body = @"This is some text.";article.author = @"Blake";// POST 創建對象.[manager postObject: article path:@"/vitural/articles" parameters: nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { /* 這個接口服務器的暫時的邏輯是:把POST過去的數據,原樣返回,以確認POST請求成功.*/ Article *article = [mappingResult firstObject]; NSLog(@"Mapped the article: %@", article); } failure:^(RKObjectRequestOperation *operation, NSError *error) { NSLog(@"Failed with error: %@", [error localizedDescription]); }];// PACTH 更新對象.article.body = @"New Body";[manager patchObject:article path:@"/vitural/articles/1234" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { /* 這個接口服務器的暫時的邏輯是:把PACTH過去的數據,原樣返回,以確認PATCH請求成功.*/ Article *article = [mappingResult firstObject]; NSLog(@"Mapped the article: %@", article);} failure:^(RKObjectRequestOperation *operation, NSError *error) { NSLog(@"Failed with error: %@", [error localizedDescription]);}];// DELETE 刪除對象./* DELETE 操作會影響上面兩個接口,最好單獨操作. */// [manager deleteObject:article path:@"/vitural/articles/1234" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {// /* 這個接口服務器的暫時的邏輯是:把DELTE過去的數據,article字段設為空,以確認DELETE請求成功.*///// Article *article = [mappingResult firstObject];// NSLog(@"Mapped the article: %@", article);// } failure:^(RKObjectRequestOperation *operation, NSError *error) {// NSLog(@"Failed with error: %@", [error localizedDescription]);// }];
// 記錄所有HTTP請求的請求和相應.RKLogConfigureByName("RestKit/Network", RKLogLevelTrace); // 記錄Core Data 的調試信息.RKLogConfigureByName("RestKit/CoreData", RKLogLevelDebug); // 記錄block的調用.RKLogWithLevelWhileExecutingBlock(RKLogLevelTrace, ^{ // 自定義日志信息. });
路由,提供了URL無關的網絡請求調用方式.它是為了在類/某個名字/某個實體聯系 與 某個URL建立某種關聯,以便再操作某個對象時,只需要告訴RestKit這個對象本身的某些屬性就可以直接發送網絡請求,而不必每次都去手動拼接 URL.
/* 設置共享的對象管理器. */ RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://dev-test.ios122.com"]]; [RKObjectManager setSharedManager: manager]; /* 將管理器與CoreData整合到一起. */ 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:@"RestKit.sqlite"]; // 此處要和自己的CoreData數據庫的名字一致. 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]; manager.managedObjectStore = managedObjectStore; // 響應描述,總是必須的. RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Article class]]; [mapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]]; NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // 任意 2xx 狀態碼. RKResponseDescriptor *articleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/vitural/articles/:articleID" keyPath:@"article" statusCodes:statusCodes]; // articleID 應為 Article 類的一個屬性. [manager addResponseDescriptor: articleDescriptor]; /* 類的路由.配置后,操作某個類時,會自動向這個類對應的地址發送請求. */ [manager.router.routeSet addRoute:[RKRoute routeWithClass:[Article class] pathPattern:@"/vitural/articles/:articleID//.json" method:RKRequestMethodGET]]; /* 發起請求. */ Article * article = [[Article alloc] init]; article.articleID = @"888"; // articleId 屬性必須給,以拼接地址路由中缺少的部分. // 因為配置了路由,所以此處不必再傳 path 參數. [manager getObject: article path:nil parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { // 處理請求成功獲取的文章. NSLog(@"Mapped the article: %@", [mappingResult firstObject]); } failure:^(RKObjectRequestOperation *operation, NSError *error) { // 處理錯誤信息. NSLog(@"%@", error.localizedDescription); }]; /* 關系路由: 使用CoreData實體間關系命名的路由.*/ /* 僅在測試CoreData關系路由時,才需要把下面一段的代碼注釋打開. */// RKEntityMapping *categoryMapping = [RKEntityMapping mappingForEntityForName:@"Category" inManagedObjectStore:manager.managedObjectStore];// // [categoryMapping addAttributeMappingsFromDictionary:@{ @"id": @"categoryID", @"name": @"name" }];// RKEntityMapping *articleMapping = [RKEntityMapping mappingForEntityForName:@"Article" inManagedObjectStore:manager.managedObjectStore];// [articleMapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]];// [articleMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"categories" toKeyPath:@"categories" withMapping:categoryMapping]];// // NSIndexSet *coreDataStatusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // 任何 2xx的狀態碼// RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:articleMapping method:RKRequestMethodAny pathPattern:@"/vitural/articles/:articleID" keyPath:@"article" statusCodes:coreDataStatusCodes];// // [manager addResponseDescriptor: responseDescriptor]; [manager.router.routeSet addRoute:[RKRoute routeWithRelationshipName:@"categories" objectClass:[Article class] pathPattern:@"/vitural/articles/:articleID//.json" method:RKRequestMethodGET]]; [manager getObjectsAtPathForRelationship:@"categories" ofObject:article parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { // 處理請求成功獲取的文章. NSLog(@"Mapped the article: %@", [mappingResult firstObject]); } failure:^(RKObjectRequestOperation *operation, NSError *error) { // 處理錯誤信息. NSLog(@"%@", error.localizedDescription); }]; /* 被命名的路由,可以根據路由名字發起相關請求. */ [manager.router.routeSet addRoute:[RKRoute routeWithName:@"article_review" pathPattern:@"/vitural/articles/:articleID//.json" method:RKRequestMethodGET]]; [manager getObjectsAtPathForRouteNamed: @"article_review" object:article parameters: nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { // 處理請求成功獲取的文章. NSLog(@"Mapped the article: %@", [mappingResult firstObject]); } failure:^(RKObjectRequestOperation *operation, NSError *error) { // 處理錯誤信息. NSLog(@"%@", error.localizedDescription); }];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://dev-test.ios122.com"]]; [RKObjectManager setSharedManager: manager]; /* 響應描述,總是必須的. */ RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Article class]]; [mapping addAttributeMappingsFromArray:@[@"title", @"author", @"body"]]; NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // 任意 2xx 狀態碼. RKResponseDescriptor *articleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:@"/vitural/articles/:articleID" keyPath:@"article" statusCodes:statusCodes]; // articleID 應為 Article 類的一個屬性. [manager addResponseDescriptor: articleDescriptor]; /* 類的路由.配置后,操作某個類時,會自動向這個類對應的地址發送請求. */ [manager.router.routeSet addRoute:[RKRoute routeWithClass:[Article class] pathPattern:@"/vitural/articles/:articleID//.json" method:RKRequestMethodPOST]]; Article *article = [[Article alloc]init]; article.articleID = @"666"; UIImage *image = [UIImage imageNamed:@"test.jpg"]; // 工程中要確實存在一張名為 test.jpg 的照片. // 序列化對象屬性,以添加附件. NSMutableURLRequest *request = [[RKObjectManager sharedManager] multipartFormRequestWithObject:article method:RKRequestMethodPOST path:nil parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { [formData appendPartWithFileData:UIImagePNGRepresentation(image) name:@"myImg" // 這個字段要和服務器取文件的字段一致. fileName:@"photo.jpg" mimeType:@"image/jpeg"]; }]; RKObjectRequestOperation *operation = [[RKObjectManager sharedManager] objectRequestOperationWithRequest:request success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { /* 服務器端接口目前自定義的邏輯是: 成功后,會返回圖片上傳后的服務器地址. */ NSLog(@"Mapped the article: %@", [mappingResult firstObject]); } failure:^(RKObjectRequestOperation *operation, NSError *error) { NSLog(@"%@", error.localizedDescription); }]; [[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation]; // 注意:要用enqueued,不要使用 started方法.
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://dev-test.ios122.com"]]; Article * articleA = [[Article alloc] init]; articleA.articleID = @"888"; Article * articleB = [[Article alloc] init]; articleB.articleID = @"1234"; Article * articleC = [[Article alloc] init]; articleC.articleID = @"555"; /* 以隊列方式,發送多個請求. */ [manager.router.routeSet addRoute:[RKRoute routeWithClass:[Article class] pathPattern:@"/vitural/articles/:articleID//.json" method:RKRequestMethodGET]]; RKRoute * route = [RKRoute routeWithClass:[Article class] pathPattern:@"/vitural/articles/:articleID//.json" method:RKRequestMethodPOST]; [manager enqueueBatchOfObjectRequestOperationsWithRoute:route objects:@[articleA, articleB, articleC] progress:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) { NSLog(@"完成了 %lu 個操作", (unsigned long)numberOfFinishedOperations); } completion:^ (NSArray *operations) { NSLog(@"所有的文章都已獲取!"); }];
可以將一個JSON文件轉化為一個數據庫,用于初始化應用.
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:@"RestKit.sqlite"]; // 此處要和自己的CoreData數據庫的名字一致. 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]; // 使用 RKEntityMapping 從工程文件 "articles.json" 導入數據. // JSON 類似于: {"articles": [ {"title": "Article 1", "body": "Text", "author": "Blake" ]} error = nil; NSBundle *mainBundle = [NSBundle mainBundle]; [importer importObjectsFromItemAtPath:[mainBundle pathForResource:@"articles" ofType:@"json"] // 工程中要有這個文件. withMapping:articleMapping keyPath:@"articles" error:&error]; success = [importer finishImporting:&error]; if (success) { [importer logSeedingInfo]; }
// 要額外添加頭文件: #import <RestKit/Search.h>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);
// 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];
新聞熱點
疑難解答