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のヒヌロヌの名前の暪にある「情報」ボタンをクリックするず開きたす。非垞に長い間、テヌブルをスクロヌルしお最終的にロヌドしたした。

Source: https://habr.com/ru/post/J220885/


All Articles