Uproszczenie korzystania z RESTful API i utrwalania danych na iOS z Mantle i Realm

Opublikowany: 2022-03-11

Każdy programista iOS jest zaznajomiony z Core Data, schematem obiektowym i strukturą trwałości od Apple. Oprócz lokalnego utrwalania danych platforma zawiera szereg zaawansowanych funkcji, takich jak śledzenie zmian obiektów i cofanie zmian. Te funkcje, choć przydatne w wielu przypadkach, nie są darmowe. Wymaga dużo kodu, a framework jako całość ma stromą krzywą uczenia się.

W 2014 roku została wydana mobilna baza danych Realm, która szturmem podbiła świat deweloperski. Jeśli wszystko, czego potrzebujemy, to utrwalanie danych lokalnie, Realm jest dobrą alternatywą. W końcu nie wszystkie przypadki użycia wymagają zaawansowanych funkcji Core Data. Realm jest niezwykle łatwy w użyciu i w przeciwieństwie do Core Data wymaga bardzo niewielkiej ilości kodu wzorcowego. Jest również bezpieczny dla wątków i mówi się, że jest szybszy niż struktura trwałości od Apple.

W większości nowoczesnych aplikacji mobilnych utrzymywanie danych rozwiązuje połowę problemu. Często musimy pobierać dane z usługi zdalnej, zwykle za pośrednictwem interfejsu API RESTful. W tym miejscu do gry wkracza Mantle. Jest to model open-source dla Cocoa i Cocoa Touch. Mantle znacznie upraszcza pisanie modeli danych do interakcji z interfejsami API, które używają JSON jako formatu wymiany danych.

Realm and Mantle na iOS

W tym artykule będziemy tworzyć aplikację na iOS, która będzie pobierać listę artykułów wraz z linkami do nich z interfejsu API wyszukiwania artykułów New York Times v2. Lista będzie pobierana za pomocą standardowego żądania HTTP GET, z modelami żądań i odpowiedzi utworzonymi za pomocą Mantle. Zobaczymy, jak łatwo z Mantle radzić sobie z przekształceniami wartości (np. z NSDate na string). Po pobraniu danych utrwalimy je lokalnie za pomocą Realm. Wszystko to przy minimalnym kodzie standardowym.

RESTful API — wprowadzenie

Zacznijmy od stworzenia nowego projektu Xcode „Master-Detail Application” dla systemu iOS o nazwie „RealmMantleTutorial”. Będziemy dodawać do niego frameworki za pomocą CocoaPods. Podfile powinien przypominać następujący:

 pod 'Mantle' pod 'Realm' pod 'AFNetworking'

Po zainstalowaniu podów możemy otworzyć nowo utworzony obszar roboczy MantleRealmTutorial . Jak już zauważyłeś, zainstalowano również słynną platformę AFNetworking. Będziemy go używać do wykonywania żądań do API.

Jak wspomniano we wstępie, New York Times zapewnia doskonały interfejs API do wyszukiwania artykułów. Aby z niego skorzystać, należy zarejestrować się w celu uzyskania klucza dostępu do API. Można to zrobić pod adresem http://developer.nytimes.com. Mając klucz API w ręku, jesteśmy gotowi do rozpoczęcia kodowania.

Zanim zagłębimy się w tworzenie modeli danych Mantle, musimy przygotować i uruchomić naszą warstwę sieciową. Stwórzmy nową grupę w Xcode i nazwijmy ją Network. W tej grupie będziemy tworzyć dwie klasy. Nazwijmy pierwszą klasę SessionManager i upewnijmy się, że wywodzi się z AFHTTPSessionManager , która jest klasą menedżera sesji z AFNetworking , zachwycającej struktury sieciowej. Nasza klasa SessionManager będzie pojedynczym obiektem, którego będziemy używać do wykonywania żądań pobierania do API. Po utworzeniu klasy skopiuj poniższy kod odpowiednio do plików interfejsu i implementacji.

 #import "AFHTTPSessionManager.h" @interface SessionManager : AFHTTPSessionManager + (id)sharedManager; @end
 #import "SessionManager.h" static NSString *const kBaseURL = @"http://api.nytimes.com"; @implementation SessionManager - (id)init { self = [super initWithBaseURL:[NSURL URLWithString:kBaseURL]]; if(!self) return nil; self.responseSerializer = [AFJSONResponseSerializer serializer]; self.requestSerializer = [AFJSONRequestSerializer serializer]; return self; } + (id)sharedManager { static SessionManager *_sessionManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sessionManager = [[self alloc] init]; }); return _sessionManager; } @end

Menedżer sesji jest inicjowany za pomocą podstawowego adresu URL zdefiniowanego w statycznej zmiennej kBaseURL . Będzie również używać serializatorów żądań i odpowiedzi JSON.

Teraz druga klasa, którą stworzymy w grupie Network , będzie nazywała się APIManager . Pochodzi z naszej nowo utworzonej klasy SessionManager . Po utworzeniu niezbędnych modeli danych dodamy do ApiManager metodę, która będzie używana do żądania listy artykułów z API.

Przegląd interfejsu API wyszukiwania artykułów w New York Times

Oficjalna dokumentacja tego doskonałego interfejsu API jest dostępna pod adresem http://developer.nytimes.com/…/article_search_api_v2. To, co zamierzamy zrobić, to użyć następującego punktu końcowego:

 http://api.nytimes.com/svc/search/v2/articlesearch

… aby pobrać artykuły znalezione przy użyciu wybranego przez nas hasła wyszukiwania ograniczonego zakresem dat. Na przykład możemy poprosić API o zwrócenie listy wszystkich artykułów, które pojawiły się w New York Times, które miały coś wspólnego z koszykówką w ciągu pierwszych siedmiu dni lipca 2015 r. Zgodnie z dokumentacją API, aby to zrobić musimy ustawić następujące parametry w żądaniu get do tego punktu końcowego:

Parametr Wartość
Q "Koszykówka"
Data rozpoczęcia „20150701”
Data zakonczenia „20150707”

Odpowiedź z API jest dość złożona. Poniżej znajduje się odpowiedź na żądanie z powyższymi parametrami ograniczonymi tylko do jednego artykułu (jednej pozycji w tablicy dokumentów) z pominięciem wielu pól dla jasności.

 { "response": { "docs": [ { "web_url": "http://www.nytimes.com/2015/07/04/sports/basketball/robin-lopez-and-knicks-are-close-to-a-deal.html", "lead_paragraph": "Lopez, a 7-foot center, joined Arron Afflalo, a 6-foot-5 guard, as the Knicks' key acquisitions in free agency. He is expected to solidify the Knicks' interior defense.", "abstract": null, "print_page": "1", "source": "The New York Times", "pub_date": "2015-07-04T00:00:00Z", "document_type": "article", "news_desk": "Sports", "section_name": "Sports", "subsection_name": "Pro Basketball", "type_of_material": "News", "_id": "5596e7ac38f0d84c0655cb28", "word_count": "879" } ] }, "status": "OK", "copyright": "Copyright (c) 2013 The New York Times Company. All Rights Reserved." }

W odpowiedzi otrzymujemy zasadniczo trzy pola. Pierwsza z nich o nazwie response zawiera tablicę docs , która z kolei zawiera elementy reprezentujące artykuły. Dwa pozostałe pola to status i prawa autorskie . Teraz, gdy wiemy już, jak działa API, nadszedł czas na stworzenie modeli danych za pomocą Mantle.

Wprowadzenie do płaszcza

Jak wspomniano wcześniej, Mantle to framework o otwartym kodzie źródłowym, który znacznie upraszcza pisanie modeli danych. Zacznijmy od stworzenia modelu żądania listy artykułów. Nazwijmy tę klasę ArticleListRequestModel i upewnijmy się, że pochodzi od MTLModel , czyli klasy, z której powinny pochodzić wszystkie modele Mantle. Dodatkowo dostosujmy go do protokołu MTLJSONSerializing . Nasz model żądania powinien mieć trzy właściwości odpowiednich typów: query, ArticlesFromDate i ArticlesToDate . Aby upewnić się, że nasz projekt jest dobrze zorganizowany, proponuję umieścić tę klasę w grupie Modelki .

Mantle upraszcza pisanie modeli danych, redukuje kod wzorcowy.
Ćwierkać

Oto jak powinien wyglądać plik interfejsu ArticleListRequestModel :

 #import "MTLModel.h" #import "Mantle.h" @interface ArticleListRequestModel : MTLModel <MTLJSONSerializing> @property (nonatomic, copy) NSString *query; @property (nonatomic, copy) NSDate *articlesFromDate; @property (nonatomic, copy) NSDate *articlesToDate; @end

Jeśli teraz przeszukamy dokumentację naszego punktu końcowego wyszukiwania artykułów lub spojrzymy na tabelę z powyższymi parametrami żądania, zauważymy, że nazwy zmiennych w żądaniu API różnią się od tych w naszym modelu żądania. Mantle radzi sobie z tym skutecznie, stosując metodę:

 + (NSDictionary *)JSONKeyPathsByPropertyKey.

Oto jak ta metoda powinna zostać zaimplementowana w implementacji naszego modelu żądania:

 #import "ArticleListRequestModel.h" @implementation ArticleListRequestModel #pragma mark - Mantle JSONKeyPathsByPropertyKey + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @"query": @"q", @"articlesFromDate": @"begin_date", @"articlesToDate": @"end_date" }; } @end

Implementacja tej metody określa, w jaki sposób właściwości modelu są mapowane na jego reprezentacje JSON. Po zaimplementowaniu metody JSONKeyPathsByPropertyKey możemy uzyskać słownikową reprezentację modelu w formacie JSON za pomocą metody klasy +[MTLJSONAdapter JSONArrayForModels:] .

Jedyną rzeczą, która pozostała, jak wiemy z listy parametrów, jest to, że oba parametry daty muszą mieć format „RRRRMMDD”. W tym miejscu Mantle jest bardzo przydatny. Możemy dodać niestandardową transformację wartości dla dowolnej właściwości, implementując opcjonalną metodę +<propertyName>JSONTransformer . Implementując go, mówimy Mantle, jak wartość konkretnego pola JSON powinna zostać przekształcona podczas deserializacji JSON. Możemy również zaimplementować transformator odwracalny, który zostanie wykorzystany podczas tworzenia JSON z modelu. Ponieważ musimy przekształcić obiekt NSDate w ciąg znaków, skorzystamy również z klasy NSDataFormatter . Oto pełna implementacja klasy ArticleListRequestModel :

 #import "ArticleListRequestModel.h" @implementation ArticleListRequestModel + (NSDateFormatter *)dateFormatter { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateFormat = @"yyyyMMdd"; return dateFormatter; } #pragma mark - Mantle JSONKeyPathsByPropertyKey + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @"query": @"q", @"articlesFromDate": @"begin_date", @"articlesToDate": @"end_date" }; } #pragma mark - JSON Transformers + (NSValueTransformer *)articlesToDateJSONTransformer { return [MTLValueTransformer transformerUsingForwardBlock:^id(NSString *dateString, BOOL *success, NSError *__autoreleasing *error) { return [self.dateFormatter dateFromString:dateString]; } reverseBlock:^id(NSDate *date, BOOL *success, NSError *__autoreleasing *error) { return [self.dateFormatter stringFromDate:date]; }]; } + (NSValueTransformer *)articlesFromDateJSONTransformer { return [MTLValueTransformer transformerUsingForwardBlock:^id(NSString *dateString, BOOL *success, NSError *__autoreleasing *error) { return [self.dateFormatter dateFromString:dateString]; } reverseBlock:^id(NSDate *date, BOOL *success, NSError *__autoreleasing *error) { return [self.dateFormatter stringFromDate:date]; }]; } @end

Kolejną wielką cechą Mantle jest to, że wszystkie te modele są zgodne z protokołem NSCoding , a także implementują metody isEqual i hash .

Jak już widzieliśmy, wynikowy JSON z wywołania API zawiera tablicę obiektów reprezentujących artykuły. Jeśli chcemy modelować tę odpowiedź za pomocą Mantle, będziemy musieli stworzyć dwa oddzielne modele danych. Jeden modelowałby obiekty reprezentujące artykuły (elementy tablicy docs ), a drugi modelowałby całą odpowiedź JSON z wyjątkiem elementów tablicy docs. Teraz nie musimy mapować każdej właściwości z przychodzącego JSON do naszych modeli danych. Załóżmy, że interesują nas tylko dwa pola obiektów artykułów, a będą to lead_paragraph i web_url . Jak widać poniżej, implementacja klasy ArticleModel jest dość prosta.

 #import "MTLModel.h" #import <Mantle/Mantle.h> @interface ArticleModel : MTLModel <MTLJSONSerializing> @property (nonatomic, copy) NSString *leadParagraph; @property (nonatomic, copy) NSString *url; @end
 #import "ArticleModel.h" @implementation ArticleModel #pragma mark - Mantle JSONKeyPathsByPropertyKey + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @"leadParagraph": @"lead_paragraph", @"url": @"web_url" }; } @end

Teraz, gdy model artykułu został zdefiniowany, możemy zakończyć definicję modelu odpowiedzi, tworząc model dla listy artykułów. Oto jak będzie wyglądał model odpowiedzi klasy ArticleList.

 #import "MTLModel.h" #import <Mantle/Mantle.h> #import "ArticleModel.h" @interface ArticleListResponseModel : MTLModel <MTLJSONSerializing> @property (nonatomic, copy) NSArray *articles; @property (nonatomic, copy) NSString *status; @end
 #import "ArticleListResponseModel.h" @class ArticleModel; @implementation ArticleListResponseModel #pragma mark - Mantle JSONKeyPathsByPropertyKey + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @"articles" : @"response.docs", @"status" : @"status" }; } #pragma mark - JSON Transformer + (NSValueTransformer *)articlesJSONTransformer { return [MTLJSONAdapter arrayTransformerWithModelClass:ArticleModel.class]; } @end

Ta klasa ma tylko dwie właściwości: status i artykuły . Jeśli porównamy to z odpowiedzią z punktu końcowego, zobaczymy, że trzeci atrybut praw autorskich JSON nie zostanie zmapowany do modelu odpowiedzi. Jeśli spojrzymy na metodę itemsJSONTransformer , zobaczymy, że zwraca ona transformator wartości dla tablicy zawierającej obiekty klasy ArticleModel .

Warto również zauważyć, że w metodzie JSONKeyPathsByPropertyKey artykuły właściwości modelu odpowiadają tablicy docs zagnieżdżonej w odpowiedzi atrybutu JSON.

Do tej pory powinniśmy mieć zaimplementowane trzy klasy modeli: ArticleListRequestModel, ArticleModel i ArticleListResponseModel.

Pierwsze żądanie API

Spokojny interfejs API

Teraz, gdy zaimplementowaliśmy wszystkie modele danych, nadszedł czas, aby wrócić do klasy APIManager , aby zaimplementować metodę, której użyjemy do wykonywania żądań GET do API. Metoda:

 - (NSURLSessionDataTask *) getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure

przyjmuje model żądania ArticleListRequestModel jako parametr i zwraca ArticleListResponseModel w przypadku powodzenia lub NSError w przeciwnym razie. Implementacja tej metody wykorzystuje AFNetworking do wykonania żądania GET do interfejsu API. Należy pamiętać, że w celu pomyślnego wykonania żądania API musimy podać klucz, który można uzyskać, jak wspomniano wcześniej, rejestrując się na stronie http://developer.nytimes.com.

 #import "SessionManager.h" #import "ArticleListRequestModel.h" #import "ArticleListResponseModel.h" @interface APIManager : SessionManager - (NSURLSessionDataTask *)getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure; @end
 #import "APIManager.h" #import "Mantle.h" static NSString *const kArticlesListPath = @"/svc/search/v2/articlesearch.json"; static NSString *const kApiKey = @"replace this with your own key"; @implementation APIManager - (NSURLSessionDataTask *)getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure{ NSDictionary *parameters = [MTLJSONAdapter JSONDictionaryFromModel:requestModel error:nil]; NSMutableDictionary *parametersWithKey = [[NSMutableDictionary alloc] initWithDictionary:parameters]; [parametersWithKey setObject:kApiKey forKey:@"api-key"]; return [self GET:kArticlesListPath parameters:parametersWithKey success:^(NSURLSessionDataTask *task, id responseObject) { NSDictionary *responseDictionary = (NSDictionary *)responseObject; NSError *error; ArticleListResponseModel *list = [MTLJSONAdapter modelOfClass:ArticleListResponseModel.class fromJSONDictionary:responseDictionary error:&error]; success(list); } failure:^(NSURLSessionDataTask *task, NSError *error) { failure(error); }]; }

Przy wdrażaniu tej metody dzieją się dwie bardzo ważne rzeczy. Najpierw spójrzmy na tę linię:

 NSDictionary *parameters = [MTLJSONAdapter JSONDictionaryFromModel:requestModel error:nil];

Dzieje się tak, że korzystając z metody dostarczonej przez klasę MTLJSONAdapter otrzymujemy reprezentację NSDictionary naszego modelu danych. Ta reprezentacja odzwierciedla JSON, który zostanie wysłany do interfejsu API. W tym tkwi piękno płaszcza. Po zaimplementowaniu metod JSONKeyPathsByPropertyKey i +<propertyName>JSONTransformer w klasie ArticleListRequestModel, możemy błyskawicznie uzyskać poprawną reprezentację JSON naszego modelu danych za pomocą zaledwie jednego wiersza kodu.

Płaszcz pozwala nam również na dokonywanie przekształceń również w innym kierunku. I dokładnie to dzieje się z danymi otrzymanymi z API. Otrzymany NSDictionary jest mapowany na obiekt klasy ArticleListResponseModel przy użyciu następującej metody klasy:

 ArticleListResponseModel *list = [MTLJSONAdapter modelOfClass:ArticleListResponseModel.class fromJSONDictionary:responseDictionary error:&error];

Trwałe dane z Realm

Teraz, gdy jesteśmy w stanie pobrać dane ze zdalnego interfejsu API, nadszedł czas, aby je utrwalić. Jak wspomniano we wstępie, zrobimy to za pomocą Realm. Realm to mobilna baza danych, która zastępuje Core Data i SQLite. Jak zobaczymy poniżej, jest niezwykle łatwy w użyciu.

Realm, najlepsza mobilna baza danych, jest idealnym zamiennikiem dla Core Data i SQLite.
Ćwierkać

Aby zapisać fragment danych w Realm, najpierw musimy zahermetyzować obiekt, który pochodzi z klasy RLObject. Teraz musimy stworzyć klasę modelu, która będzie przechowywać dane dla pojedynczych artykułów. Oto jak łatwo stworzyć taką klasę.

 #import "RLMObject.h" @interface ArticleRealm : RLMObject @property NSString *leadParagraph; @property NSString *url; @end

I to mogłoby być w zasadzie to, implementacja tej klasy mogłaby pozostać pusta. Należy pamiętać, że właściwości w klasie modelu nie mają atrybutów, takich jak nieatomowe, silne lub kopia. Realm się nimi zajmuje i nie musimy się nimi martwić.

Ponieważ artykuły, które możemy uzyskać, są modelowane za pomocą modelu Mante Article , wygodnie byłoby zainicjować obiekty ArticleRealm z obiektami klasy Article . W tym celu dodamy metodę initWithMantleModel do naszego modelu Realm. Oto pełna implementacja klasy ArticleRealm .

 #import "RLMObject.h" #import "ArticleModel.h" @interface ArticleRealm : RLMObject @property NSString *leadParagraph; @property NSString *url; - (id)initWithMantleModel:(ArticleModel *)articleModel; @end
 #import "ArticleRealm.h" @implementation ArticleRealm - (id)initWithMantleModel:(ArticleModel *)articleModel{ self = [super init]; if(!self) return nil; self.leadParagraph = articleModel.leadParagraph; self.url = articleModel.url; return self; } @end

Współdziałamy z bazą danych za pomocą obiektów klasy RLMRealm . Możemy łatwo uzyskać obiekt RLMRealm , wywołując metodę „[RLMRealm defaultRealm]”. Należy pamiętać, że taki obiekt jest ważny tylko w obrębie wątku, w którym został utworzony i nie może być współużytkowany przez wątki. Zapisywanie danych w Realm jest dość proste. Pojedynczy zapis lub seria zapisów musi być wykonana w ramach transakcji zapisu. Oto przykładowy zapis do bazy danych:

 RLMRealm *realm = [RLMRealm defaultRealm]; ArticleRealm *articleRealm = [ArticleRealm new]; articleRealm.leadParagraph = @"abc"; articleRealm.url = @"sampleUrl"; [realm beginWriteTransaction]; [realm addObject:articleRealm]; [realm commitWriteTransaction];

To, co się tutaj dzieje, jest następujące. Najpierw tworzymy obiekt RLMRealm do interakcji z bazą danych. Następnie tworzony jest obiekt modelu ArticleRealm (należy pamiętać, że pochodzi on z klasy RLMRealm ). Na koniec, aby go zapisać, rozpoczyna się transakcja zapisu, obiekt jest dodawany do bazy danych, a po zapisaniu transakcja zapisu zostaje zatwierdzona. Jak widać, transakcje write blokują wątek, na którym są wywoływane. Chociaż mówi się, że Realm jest bardzo szybki, gdybyśmy mieli dodać wiele obiektów do bazy danych w ramach jednej transakcji w głównym wątku, mogłoby to spowodować, że interfejs użytkownika przestanie odpowiadać do czasu zakończenia transakcji. Naturalnym rozwiązaniem jest wykonanie takiej transakcji zapisu w wątku w tle.

Żądanie API i trwała odpowiedź w Realm

To wszystkie informacje, których potrzebujemy do utrwalania artykułów przy użyciu Realm. Spróbujmy wykonać żądanie API za pomocą metody

 - (NSURLSessionDataTask *) getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure

oraz modele żądań i odpowiedzi Mantle w celu uzyskania artykułów New York Times, które miały cokolwiek wspólnego (jak w poprzednim przykładzie) z koszykówką i zostały opublikowane w ciągu pierwszych siedmiu dni czerwca 2015 r. Po udostępnieniu listy takich artykułów utrzyma go w Królestwie. Poniżej znajduje się kod, który to robi. Jest on umieszczony w metodzie viewDidLoad kontrolera widoku tabeli w naszej aplikacji.

 ArticleListRequestModel *requestModel = [ArticleListRequestModel new]; // (1) requestModel.query = @"Basketball"; requestModel.articlesToDate = [[ArticleListRequestModel dateFormatter] dateFromString:@"20150706"]; requestModel.articlesFromDate = [[ArticleListRequestModel dateFormatter] dateFromString:@"20150701"]; [[APIManager sharedManager] getArticlesWithRequestModel:requestModel // (2) success:^(ArticleListResponseModel *responseModel){ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // (3) @autoreleasepool { RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteAllObjects]; [realm commitWriteTransaction]; [realm beginWriteTransaction]; for(ArticleModel *article in responseModel.articles){ ArticleRealm *articleRealm = [[ArticleRealm alloc] initWithMantleModel:article]; // (4) [realm addObject:articleRealm]; } [realm commitWriteTransaction]; dispatch_async(dispatch_get_main_queue(), ^{ // (5) RLMRealm *realmMainThread = [RLMRealm defaultRealm]; // (6) RLMResults *articles = [ArticleRealm allObjectsInRealm:realmMainThread]; self.articles = articles; // (7) [self.tableView reloadData]; }); } }); } failure:^(NSError *error) { self.articles = [ArticleRealm allObjects]; [self.tableView reloadData]; }];

Najpierw wykonywane jest wywołanie API (2) z modelem żądania (1), który zwraca model odpowiedzi zawierający listę artykułów. Aby zachować te artykuły przy użyciu Realm, musimy utworzyć obiekty modelu Realm, co ma miejsce w pętli for (4). Należy również zauważyć, że ponieważ wiele obiektów jest utrwalanych w ramach pojedynczej transakcji zapisu, ta transakcja zapisu jest wykonywana w wątku w tle (3). Teraz, gdy wszystkie artykuły zostaną zapisane w Realm, przypisujemy je do właściwości klasy self.articles (7). Ponieważ będą one dostępne później w głównym wątku w metodach źródła danych TableView, można je bezpiecznie pobrać również z bazy danych Realm w głównym wątku (5). Ponownie, aby uzyskać dostęp do bazy danych z nowego wątku, w tym wątku należy utworzyć nowy obiekt RLMRealm (6).

Jeśli pobieranie nowych artykułów z interfejsu API nie powiedzie się z jakiegokolwiek powodu, istniejące są pobierane z pamięci lokalnej w bloku awarii.

Zawijanie

W tym samouczku dowiedzieliśmy się, jak skonfigurować Mantle, modelowy framework dla Cocoa i Cocoa Touch, w celu interakcji ze zdalnym API. Dowiedzieliśmy się również, jak lokalnie utrwalać dane pobrane w postaci obiektów modelu Mantle przy użyciu mobilnej bazy danych Realm.

Jeśli chcesz wypróbować tę aplikację, możesz pobrać kod źródłowy z repozytorium GitHub. Będziesz musiał wygenerować i podać własny klucz API przed uruchomieniem aplikacji.