RestKit 0.22.xを使用してマーベルヒーローを表示します

特にRESTアーキテクチャを使用するWebサービスは、すでに私たちの生活にしっかりと入っています。 iOS用のクライアントアプリケーションを開発する場合、多くの場合、サーバーからデータをダウンロードし、ローカルに保存/表示する必要があります。 同時に、私たち自身の「自転車」の発明に頼ることなく、これを簡単かつ自然に行いたいと思います。



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



オブジェクトの構造を検討します。

キャラクターオブジェクト
 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. }
      
      



どれが必要でしょうか? おそらく、私たちは識別子、名前、写真、説明に自分自身を制限しています。 Xcodeの* .xcdatamodeldファイルに進み、リモートオブジェクトに論理的に(部分的にではあるが)対応する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





アニメーションのオン/オフメソッドには、次のコードがあります。

animateActivityIndi​​cator:コード
 - (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のヒーローの名前の横にある「情報」ボタンをクリックすると開きます。非常に長い間、テーブルをスクロールして最終的にロードしました。








All Articles