iOSおよびOSX用の有名なObjective-C RestKitフレームワークの最新バージョンは、RESTful APIでの作業を大幅に簡素化します。 間違いなく、最も価値のある機能の1つは、 CoreDataを使用してオブジェクトをローカルデータベースに自動的に保存する機能です。 サーバーからのデータの受信から、iOSデバイスでのデータの保存と表示まで、長い道のりを歩みましょう。 そして、私たちが退屈しないように、例として、世界的に有名な漫画本会社MarvelのAPIを使用します。
この記事は一種のチュートリアルです。 読者は、iOS SDK、Core Data、およびブロックなどの概念を使用して、Objective-Cの開発の基本概念に既に精通していることが前提となっています。

1.キーを取得し、問題を定式化する
開始するには、 Marvel Webサイトで開発者として登録しましょう。
簡単な登録の後、[ アカウント ]タブに移動して、公開キーと秘密キーをコピーします。

その後、「 対話型ドキュメント」タブに移動して、API作成者が親切に提供するデータの種類を確認します。 ヒーロー、コミック、クリエイター、イベントなどのデータベースを使用する機会があります。 慣れるには、1つのことを「タッチ」するだけで十分なので、将来のアプリケーションでは、単にキャラクターのリストをアップロードして保存し、最も人気のあるキャラクターの説明も表示します。
2.はじめに
Xcodeで新しいプロジェクトを作成します。 デバイスとしてiPhoneを選択し、プロジェクト作成ウィザードウィンドウの[コアデータを使用]フィールドの横にチェックマークを残すことを忘れないでください。
ポータルに戻り、
Character
オブジェクトの構造を検討します。
キャラクターオブジェクト
どれが必要でしょうか? おそらく、私たちは識別子、名前、写真、説明に自分自身を制限しています。 Xcodeの* .xcdatamodeldファイルに進み、リモートオブジェクトに論理的に(部分的にではあるが)対応する Character { id (int, optional): The unique ID of the character resource., name (string, optional): The name of the character., description (string, optional): A short bio or description of the character., modified (Date, optional): The date the resource was most recently modified., resourceURI (string, optional): The canonical URL identifier for this resource., urls (Array[Url], optional): A set of public web site URLs for the resource., thumbnail (Image, optional): The representative image for this character., comics (ComicList, optional): A resource list containing comics which feature this character., stories (StoryList, optional): A resource list of stories in which this character appears., events (EventList, optional): A resource list of events in which this character appears., series (SeriesList, optional): A resource list of series in which this character appears. }
Character
エンティティを作成しましょう。

私は意図的に2つの識別子を作成しました。最初の
charID
は、将来の「ネイティブマーベル」の
id
を格納する役割を果たし、2番目の
innerID
はローカルでの使用に必要です。
charDescription
属性とname属性は、それぞれリモートパラメーターの説明と名前に対応しています。
また、2つの属性
thumbnailImageData
と
thumbnailURLString
作成しましたが、元の構造のパラメーターとは一致しません。 これは、JSON応答で
Image
タイプの
thumbnail
実際に辞書と一致するためです。 実際の回答の
thumbnail
オブジェクトの例を次に示します。
"thumbnail": { "path": "http://i.annihil.us/u/prod/marvel/i/mg/8/c0/4ce5a0e31f109", "extension": "jpg" }
将来的には、これをどのように使用するかを示します。
さて、Core Dataエンティティを正しく動作させるには、それを表すObjective-Cクラスも作成する必要があります。
NSManagedObject
から継承する
Character
クラスを作成します。 彼の発表は次のとおりです。
@interface Character : NSManagedObject { NSDictionary *_thumbnailDictionary; } @property (nonatomic, retain) NSString *name; @property (nonatomic, retain) NSNumber *charID; @property (nonatomic, retain) NSNumber *innerID; @property (nonatomic, retain) NSString *charDescription; @property (nonatomic, retain) NSData *thumbnailImageData; @property (nonatomic, retain) NSString *thumbnailURLString; @property NSDictionary *thumbnailDictionary; // + (NSInteger)allCharsCountWithContext:(NSManagedObjectContext *)managedObjectContext; // innerID. + (Character *)charWithManagedObjectContext:(NSManagedObjectContext *)context andInnerID:(NSInteger)charInnerID; @end
ここでは、明らかな適合性に加えて、
thumbnailDictionary
プロパティが
thumbnailDictionary
されました。これは、少し上に書いたサムネイルオブジェクトでの作業をより便利にするために追加しました。 また、プロジェクトに追加のクラスを作成しないように、2つのヘルパークラスメソッドを追加しました。
3. RestKitを使用するためのモデル
プロジェクトRestKit(以降-RK)に接続します。 これを行う方法については、 ここ (または、CocoaPodsが好きな場合はこちら)で詳しく説明します 。
次のステップは、RK、特に
RKObjectManager
や
RKManagedObjectStore
などのクラスで
GDMarvelRKObjectManager
するラッパークラス
GDMarvelRKObjectManager
(
NSObject
)を作成すること
RKManagedObjectStore
。 このクラスは作成されない場合がありますが、今後のメインビューコントローラーでコードを少しオフロードするために使用します。
RKクラスについて少し。
RKManagedObjectStore
はCore Dataのすべての作業をカプセル化するため、将来的に
NSManagedObjectContext
または
NSManagedObjectModel
直接
NSManagedObjectContext
する必要はありません。
RKObjectManager
は、オブジェクトのマッピング(一致)を使用して要求を送信し、応答を受信するための集中化されたインターフェイスを提供します。 たとえば、JSON応答で取得された必要な値は、マッピングが成功すると、オブジェクトのすべてのプロパティに自動的に割り当てられます。 記事の冒頭でそれが欲しかったのではないでしょうか?
* .hファイルにRK
#import <RestKit/RestKit.h>
を含めることを忘れないでください。
ラッパークラスにはプロパティはありませんが、2つのインスタンス変数があります。
@implementation GDMarvelRKObjectManager { RKObjectManager *objectManager; RKManagedObjectStore *managedObjectStore; }
すべてが正常に機能するように設定する必要があるものを見てみましょう。
まず、
- (id)init
メソッドで、必要なRKオブジェクトの初期化を追加します。
// AFNetworking HTTPClient NSURL *baseURL = [NSURL URLWithString:@"http://gateway.marvel.com/"]; AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL]; // RKObjectManager objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
これで、リクエストが送信されます。 Core Dataの操作はどうですか? タイプRKManagedObjectStoreのオブジェクトを構成するメソッドを作成しましょう。
- (void)configureWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel { if (!managedObjectModel) return; managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel]; NSError *error; if (!RKEnsureDirectoryExistsAtPath(RKApplicationDataDirectory(), &error)) RKLogError(@"Failed to create Application Data Directory at path '%@': %@", RKApplicationDataDirectory(), error); NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"RKMarvel.sqlite"]; if (![managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error]) RKLogError(@"Failed adding persistent store at path '%@': %@", path, error); [managedObjectStore createManagedObjectContexts]; objectManager.managedObjectStore = managedObjectStore; }
最後の行は非常に重要です。 2つの主要なRKオブジェクトである
objectManager
と
managedObjectStore
リンクします。
したがって、今後のタスクは、
GDMarvelRKObjectManager
クラスに2つの主要なアクション用のインターフェイスを作成することです。コアデータエンティティとリモートオブジェクト間のマッピング(通信)の追加、およびリモートサーバーからのこれらのオブジェクトの受信です。
最初のタスクは、次のメソッドで実装されます。
- (void)addMappingForEntityForName:(NSString *)entityName andAttributeMappingsFromDictionary:(NSDictionary *)attributeMappings andIdentificationAttributes:(NSArray *)ids andPathPattern:(NSString *)pathPattern { if (!managedObjectStore) return; RKEntityMapping *objectMapping = [RKEntityMapping mappingForEntityForName:entityName inManagedObjectStore:managedObjectStore]; // , . [objectMapping addAttributeMappingsFromDictionary:attributeMappings]; // , . , . objectMapping.identificationAttributes = ids; // , . RKResponseDescriptor *characterResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:objectMapping method:RKRequestMethodGET pathPattern:[NSString stringWithFormat:@"%@%@", MARVEL_API_PATH_PATTERN, pathPattern] keyPath:@"data.results" statusCodes:[NSIndexSet indexSetWithIndex:200]]; [objectManager addResponseDescriptor:characterResponseDescriptor]; }
ここでは、
responseDescriptorWithMapping:...
メソッドのいくつかのパラメーターに関心があります
responseDescriptorWithMapping:...
最初に、
pathPattern
パラメーター。 マクロ
MARVEL_API_PATH_PATTERN
(値
@"v1/public/"
)と入力パラメーター
pathPattern
(この例では
@"characters"
)を連結することによって取得されます。 キャラクターのリストではなく、たとえばコミックのリストを取得したい場合は、
@”comics”
という行を渡します。この行は、メソッドの本文ですでに
@"v1/public/"
接続されます。
2番目の非自明な値は、
@"data.results"
パラメーターの
@"data.results"
パラメーターです。 どこから来たの? すべてが非常に簡単です。Marvelはすべての回答を同じラッパーでラップし、その構造を見るとすべてが適切に配置されます。
キャラクターラッパー
{ "code": "int", "status": "string", "copyright": "string", "attributionText": "string", "attributionHTML": "string", "data": { "offset": "int", "limit": "int", "total": "int", "count": "int", "results": [ { "id": "int", "name": "string", "description": "string", "modified": "Date", "resourceURI": "string", "urls": [ { "type": "string", "url": "string" } ], "thumbnail": { "path": "string", "extension": "string" }, "comics": { "available": "int", "returned": "int", "collectionURI": "string", "items": [ { "resourceURI": "string", "name": "string" } ] }, "stories": { "available": "int", "returned": "int", "collectionURI": "string", "items": [ { "resourceURI": "string", "name": "string", "type": "string" } ] }, "events": { "available": "int", "returned": "int", "collectionURI": "string", "items": [ { "resourceURI": "string", "name": "string" } ] }, "series": { "available": "int", "returned": "int", "collectionURI": "string", "items": [ { "resourceURI": "string", "name": "string" } ] } } ] }, "etag": "string" }
ヒーローの実際のリストに到達する前に、RKが目的の構造に到達するためにいくつかのレベルの辞書を通過する必要があることは明らかです。 値
@"data.results"
は、「ダウン」する必要があるパスを示しています。
内部RKオブジェクトを操作するクラスの2番目のメソッドは
getMarvelObjectsAtPath
になり
getMarvelObjectsAtPath
。これは、本質的に
RKObjectManager
型のオブジェクトの
getObjectsAtPath
への呼び出しをプロキシします。 メソッドの名前は「話す」です-削除されたオブジェクトの読み込みを期待しています。 Marvel では 、リクエストごとにハッシュ、タイムスタンプ、公開キーを送信する必要があるため、これらのパラメーターの生成を
getMarvelObjectsAtPath
にカプセル化すると便利
getMarvelObjectsAtPath
。 ここにあります:
- (void)getMarvelObjectsAtPath:(NSString *)path parameters:(NSDictionary *)params success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure { // NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"yyyyMMddHHmmss"]; NSString *timeStampString = [formatter stringFromDate:[NSDate date]]; NSString *hash = [[[NSString stringWithFormat:@"%@%@%@", timeStampString, MARVEL_PRIVATE_KEY, MARVEL_PUBLIC_KEY] MD5String] lowercaseString]; NSMutableDictionary *queryParams = [NSMutableDictionary dictionaryWithDictionary:@{@"apikey" : MARVEL_PUBLIC_KEY, @"ts" : timeStampString, @"hash" : hash}]; if (params) [queryParams addEntriesFromDictionary:params]; // objectManager [objectManager getObjectsAtPath:[NSString stringWithFormat:@"%@%@", MARVEL_API_PATH_PATTERN, path] parameters:queryParams success:success failure:failure]; }
コードは
NSString
-
MD5String
上の非標準カテゴリのメソッドを使用することに注意してください。 回線からMD5-trokを生成する方法については、インターネットをご覧ください 。
このクラスには、シンプルなメソッド
- (NSManagedObjectContext *)managedObjectContext
、
- (NSManagedObjectContext *)managedObjectContext
のメインコンテキストが
managedObjectStore
ます。 また、このクラスは、インスタンスにアクセスするための
+ (GDMarvelRKObjectManager *)manager
メソッドを持つ( Singleton )シングルトンになります。
4.メインViewController
まず、基本的な
GDBaseViewController
コントローラーを作成します。このコントローラーでは、サーバーからの応答のアニメーション化された待機のサポートを、唯一の新しいメソッド
- (void)animateActivityIndicator:(BOOL)animate
。
viewDidLoad
メソッドで
viewDidLoad
タイプ
UIActivityIndicatorView
このインジケーターを作成し、取得した値をインスタンス変数
UIActivityIndicatorView *activityIndicator
割り当てて、
UIActivityIndicatorView
に追加し
self.view
。
アニメーションのオン/オフメソッドには、次のコードがあります。
animateActivityIndicator:コード
- (void)animateActivityIndicator:(BOOL)animate { activityIndicator.hidden = !animate; if (animate) { [self.view bringSubviewToFront:activityIndicator]; [activityIndicator startAnimating]; } else [activityIndicator stopAnimating]; }
さて、単一のパラメーターに
YES
値を指定してこのメソッドを呼び出すと、View Controllerは次のようになります。

次に、このクラスから継承した
GDMainViewController
Controller
GDMainViewController
作成し
GDMainViewController
。 彼の発表は次のとおりです。
@interface GDMainViewController : GDBaseViewController <UITableViewDataSource, UITableViewDelegate, UIAlertViewDelegate> { UITableView *table; NSInteger numberOfCharacters; AllAroundPullView *bottomPullView; BOOL noRequestsMade; } @end
このView Controllerでは、データベースのデータを表示します。 これを行うには、
UITableView
インスタンスを使用し
UITableView
インスタンスでは、各セルに画像と各文字の名前が表示されます。 ただし、最初はローカルデータベースが空なので、まだダウンロードする必要があります。
- (void)viewDidLoad
での
UITableView
インスタンスの作成に固有のすべての初期化プロセスの後、
GDMarvelRKObjectManager
ラッパー
GDMarvelRKObjectManager
を使用して、
RKManagedObjectStore
CoreDataモデルをRKManagedObjectStoreにバインドします。
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Marvel" withExtension:@"momd"]; [[GDMarvelRKObjectManager manager] configureWithManagedObjectModel:[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]]; // Character: [[GDMarvelRKObjectManager manager] addMappingForEntityForName:@"Character" andAttributeMappingsFromDictionary:@{ @"name" : @"name", @"id" : @"charID", @"thumbnail" : @"thumbnailDictionary", @"description" : @"charDescription" } andIdentificationAttributes:@[@"charID"] andPathPattern:MARVEL_API_CHARACTERS_PATH_PATTERN];
ご覧のとおり、リモートオブジェクトのJSONキーの名前と作成したクラスのプロパティとの対応からなる辞書は、
andAttributeMappingsFromDictionary:
パラメーターとして渡されます。
andPathPattern:
パラメーターとして、文字列
@"characters"
が渡されます(マクロ
MARVEL_API_CHARACTERS_PATH_PATTERN
)-リモートJSONオブジェクトの名前。
マッピングを追加した後、
[self loadCharacters]
メソッドを呼び出します。
彼がしていることを詳細に検討してください:
- (void)loadCharacters { numberOfCharacters = [Character allCharsCountWithContext:[[GDMarvelRKObjectManager manager] managedObjectContext]]; if (noRequestsMade && numberOfCharacters > 0) { noRequestsMade = NO; return; } [self animateActivityIndicator:YES]; noRequestsMade = NO; [[GDMarvelRKObjectManager manager] getMarvelObjectsAtPath:MARVEL_API_CHARACTERS_PATH_PATTERN parameters:@{@"offset" : @(numberOfCharacters)} success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { [self animateActivityIndicator:NO]; NSInteger newInnerID = numberOfCharacters; for (Character *curCharacter in mappingResult.array) { if ([curCharacter isKindOfClass:[Character class]]) { curCharacter.innerID = @(newInnerID); newInnerID++; // ( ), , [self saveToStore]; } } numberOfCharacters = newInnerID; [table reloadData]; bottomPullView.hidden = NO; [bottomPullView finishedLoading]; } failure:^(RKObjectRequestOperation *operation, NSError *error) { [bottomPullView finishedLoading]; [[[UIAlertView alloc] initWithTitle:@"Marvel API Error" message:operation.error.localizedDescription delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Retry", nil] show]; }]; }
最初に、ローカルデータベースから文字の総数を取得します。この値は、メインテーブルのセルの数に対応します。 アプリケーションを最初に起動すると、もちろんゼロになります。 サーバーにアクセスするときに、送信されたオフセットパラメーターと同じ値を使用します。 したがって、以降の各リクエストに対して、Marvelサーバーは新しいヒーローオブジェクトのみを返します(デフォルトでは、ヒーローはそれぞれ20個のパックを返します)。
次に、
getMarvelObjectsAtPath
ラッパー
getMarvelObjectsAtPath
を使用して同じメインリクエストを
getMarvelObjectsAtPath
ます。
このメソッドには、今私たちにとって重要な2つのパラメーターがあります。これらは成功と失敗です。それぞれ、クエリ実行の成功と失敗の結果の動作を記述するブロックです。 そのため、文字の配列を正常に受信すると、各文字の
innerID
を生成し、ローカルデータベースに保存して、文字の総数の値を変更します。 次に、テーブルの表示を更新します。 ここでの主な魔法は、この段階で、受信したオブジェクトがすでにCoreDataストレージに自動的に保存されていることです-RKがそれを行いました。 (これは、マッピングの一致が指定されたオブジェクトのフィールド/プロパティにのみ適用されることに注意する価値があります。したがって、上記のコードでは、
[self saveToStore]
呼び出して
innerID
パラメーターの変更を個別に保存する必要があります)。
エラーが発生した場合、ユーザーに表示するだけで、テーブルは更新しません。
コードは次のストレージメソッドを使用します。
- (void)saveToStore { NSError *saveError; if (![[[GDMarvelRKObjectManager manager] managedObjectContext] saveToPersistentStore:&saveError]) XLog(@"%@", [saveError localizedDescription]); }
また、
bottomPullView
インスタンス
bottomPullView
への参照にも注目してください。 この変数は、タイプ
AllAroundPullView
( GitHubから
AllAroundPullView
)のオブジェクトを保存します。これは、
UIScrollView
すべての側面からPull-To-Resfresh動作を実装するのに役立つ便利なコントロールです。 キャラクターの次の各部分をロードし、テーブルの下端に到達して引き上げます。
以前の
- (void)viewDidLoad
このコントロールは次のように初期化され、使用されました。
bottomPullView = [[AllAroundPullView alloc] initWithScrollView:table position:AllAroundPullViewPositionBottom action:^(AllAroundPullView *view){ [self loadCharacters]; }]; bottomPullView.hidden = YES; [table addSubview:bottomPullView];
ご覧のとおり、パラメーターアクションとして渡されるブロックの本体に、新しいヒーローを読み込むための同じメソッド
loadCharacters
ます。
さて、エミュレータでアプリケーションを実行し、最初の成功した応答を待ちます。 すべてが
I restkit.network:RKObjectRequestOperation.m:220 GET 'http://your-url.here' (200 OK / 20 objects)
、RKロガーが
I restkit.network:RKObjectRequestOperation.m:220 GET 'http://your-url.here' (200 OK / 20 objects)
ようなもの
I restkit.network:RKObjectRequestOperation.m:220 GET 'http://your-url.here' (200 OK / 20 objects)
場合、すべてが正常であり、確認できますオブジェクトがベースに保持されるかどうか。
これを行うには、エミュレーターフォルダーに移動し、アプリケーションとDocumentsフォルダーを見つけます。
RKMarvel.sqlite
ベースが
RKMarvel.sqlite
はずです(これは、以前に
addSQLitePersistentStoreAtPath:
メソッドを呼び出すときにパラメーターとして指定した名前です)。 このベースをSQLite-editorで開き、キャラクターが保存されていることを確認しましょう。

やった! 一部のヒーローには、小さな説明さえあります。 この「良い」ものすべてを表示する時間です。
5.画像とディスプレイの保存。
せっかちな読者が彼の好きなキャラクターの画像を見たいとずっと思っていたことを知っています。 これを行うには、テーブルの外観をカスタマイズする必要があります。
UITableView
型のオブジェクトの作成と設定の技術的な詳細は説明しません(読者は読者が既にこれを知っていると想定しています)が、すぐにセルを作成するテーブルのデリゲートメソッドに進みます。
tableView:cellForRowAtIndexPath:コード
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSInteger row = indexPath.row; NSString *reusableIdentifier = [NSString stringWithFormat:@"%d", row % 2]; UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:reusableIdentifier]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reusableIdentifier]; cell.autoresizingMask = UIViewAutoresizingFlexibleWidth; } [[cell.contentView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; if (numberOfCharacters > row) { Character *curCharacter = [Character charWithManagedObjectContext: [[GDMarvelRKObjectManager manager] managedObjectContext] andInnerID:row]; if (curCharacter) { BOOL charHasDescription = ![curCharacter.charDescription isEqualToString:@""]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(70, 0, CGRectGetWidth(cell.contentView.frame) - 70 - (charHasDescription ? 60 : 0), 60)]; label.backgroundColor = [UIColor clearColor]; label.text = curCharacter.name; label.autoresizingMask = UIViewAutoresizingFlexibleWidth; [cell.contentView addSubview:label]; GDCellThumbnailView *thumbnail = [GDCellThumbnailView thumbnail]; if (curCharacter.thumbnailImageData) [thumbnail setImage:[UIImage imageWithData:curCharacter.thumbnailImageData]]; else [self loadThumbnail:thumbnail fromURLString:curCharacter.thumbnailURLString forCharacter:curCharacter]; [cell.contentView addSubview:thumbnail]; cell.accessoryType = charHasDescription ? UITableViewCellAccessoryDetailButton : UITableViewCellSelectionStyleNone; cell.selectionStyle = charHasDescription ? UITableViewCellSelectionStyleGray : UITableViewCellSelectionStyleNone; } } return cell; }
次のセルを作成した後、目的のヒーローをデータベースから取得し、その名前を表示します。また、彼に関する詳細情報があるかどうかを確認し、セルにボタンを配置します。クリックすると、この情報が表示されます。 まあ、そして最も重要なこと-キャラクターのイメージ。 このために、特別なクラス
GDCellThumbnailView
を作成し、そのインスタンスをセルに配置しました。 特別なことは何もせず、サムネイルが読み込まれるまで待機する「回転する花」を表示するだけです。
loadThumbnail:fromURLString:forCharacter:
メソッドが空の場合、メインビューコントローラーは次のようになります。

ヒーローの写真を読み込むためのメソッドを実装しましょう。 RKにはすでに
AFNetworking
フレームワークが含まれているため、これを使用して、写真をアップロードするための非同期要求をMarvelサーバーに送信します。
- (void)loadThumbnail:(GDCellThumbnailView *)view fromURLString:(NSString *)urlString forCharacter:(Character *)character { XLog(@"Loading thumbnail for %@", character.name); AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { character.thumbnailImageData = responseObject; [self saveToStore]; [view setImage:[UIImage imageWithData:responseObject]]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { XLog(@"%@", [error localizedDescription]); }]; [operation start]; }
以上です。 アプリケーションを再度起動します。 すでに良い結果です。

これで停止するのは難しくなりますが、許可を得て、便利なPull-To-Refreshコントロールを使用してより多くのキャラクターをロードします。 同時に、現在のベースの外観を確認します。


これで、インターネットに接続しているかどうかに関係なく、ヒーローに関する写真と情報(もちろん、ダウンロードしたものだけ)の両方がローカルに保存されます。
6.結論。
RestKitはタスクに完全に対応しました。リクエストが送信され、レスポンスが受信され、オブジェクトが自動的に保存されます。この記事で提供されているロードと表示の原則を誰もが好むとは限りません。データベース全体をすぐにデフレートし、ローカルで完全に操作する方が合理的である可能性があります。著者は、RKの基本的な機能を理解するには、そのような機能で十分であると考えています。プロジェクト全体のソースコード(および特定のキャラクターに関する情報を表示するこの記事にない部分)は、GitHubからダウンロードできます。記事へのコメントとして、またGitHubでのプールリクエストとして、あなたの希望とコメントを歓迎します。
最後に、別の画像をお願いします。今回は、2番目のView Controllerのスクリーンショットです。メインView Controllerのヒーローの名前の横にある「情報」ボタンをクリックすると開きます。非常に長い間、テーブルをスクロールして最終的にロードしました。
