Iga iOS-i arendaja tunneb Apple'i põhiandmeid, objekti-graafikut ja püsivuse raamistikku. Lisaks kohalikule andmete püsimisele on raamistikul hulgaliselt täiustatud funktsioone, näiteks objekti muutmise jälgimine ja tagasivõtmine. Kuigi need funktsioonid on paljudel juhtudel kasulikud, ei tule need tasuta. See nõuab palju katlakoodi ja raamistik tervikuna on järsu õppimiskõveraga.
2014. aastal Valdkond , mobiilne andmebaas, vabastati ja haaras arengumaailma tormiga. Kui meil on vaja ainult andmete kohalikku säilitamist, on Realm hea alternatiiv. Lõppude lõpuks ei nõua kõik kasutusjuhtumid põhiandmete täiustatud funktsioone. Realm on äärmiselt lihtne kasutada ja erinevalt põhiandmetest nõuab see väga vähe katlakoodi. See on ka niidikindel ja väidetavalt kiirem kui Apple'i püsiv raamistik.
Enamikus kaasaegsetes mobiilirakendustes lahendavad püsivad andmed poole probleemist. Sageli peame andmeid hankima kaugteenusest, tavaliselt RESTful API kaudu. See on koht Mantel mängu tuleb. See on Cocoa ja Cocoa Touchi avatud lähtekoodiga mudelraamistik. Mantle lihtsustab oluliselt andmemudelite kirjutamist kasutatavate API-dega suhtlemiseks JSON nende andmevahetusformaadina.
Selles artiklis ehitame iOS-i rakenduse, mis toob artiklite loendi koos linkidega neile New York Timesi artiklite otsingu API v2-st. Loendi toomine toimub tavalise HTTP GET-päringu abil, taotluste ja vastuste mudelid on loodud Mantle'i abil. Saame teada, kui lihtne on Mantle'iga väärtuste teisendusi käsitseda (nt NSDate'ist stringini). Kui andmed on hangitud, säilitame need kohapeal, kasutades Realmi. Seda kõike minimaalse katlakoodiga.
Alustame uue iOS-i projekti 'Master-Detail Application' Xcode nimega 'RealmMantleTutorial' loomisega. Lisame sellele raamistikud CocoaPodide abil. Podfail peaks sarnanema järgmisega:
pod 'Mantle' pod 'Realm' pod 'AFNetworking'
Kui kaunad on paigaldatud, saame äsja loodud avada MantleRealmTutorial tööruum. Nagu märkasite, on installitud ka kuulus AFNetworking raamistik. Kasutame seda API-le päringute esitamiseks.
Nagu sissejuhatuses mainitud, pakub New York Times suurepärast artiklite otsimise API-d. Selle kasutamiseks tuleb API-le juurdepääsuvõtme saamiseks registreeruda. Seda saab teha aadressil http://developer.nytimes.com . Kui API-võti on käes, oleme valmis kodeerimisega alustama.
Enne Mantle'i andmemudelite loomisse süvenemist peame oma võrgukihi tööle panema. Loome uue rühma Xcode'is ja nimetame seda võrguks. Selles grupis loome kaks klassi. Helistame esimeseks SessionManager ja veenduge, et see pärineks AFHTTPSessionManager mis on seansihalduri klass alates AFVõrgustik , veetlev võrgustike raamistik. Meie SessionManager klass on üksikobjekt, mida kasutame API-le päringute hankimiseks. Kui klass on loodud, kopeerige palun allolev kood vastavalt liidese- ja juurutusfailidesse.
#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
Seansihaldur lähtestatakse staatiliselt määratletud põhi-URL-iga kBaseURL muutuv. Samuti kasutatakse JSON-i päringu- ja vastuserialiseerijaid.
Nüüd teine klass, mille me loome Võrk rühm kutsutakse APIManager . See tuletatakse meie äsja loodud SessionManager klass. Kui vajalikud andmemudelid on loodud, lisame sellele meetodi ApiManager mida kasutatakse API-st artiklite loendi taotlemiseks.
Selle suurepärase API ametlik dokumentatsioon on saadaval aadressil http://developer.nytimes.com/…/article_search_api_v2 . Mida me kavatseme teha, on kasutada järgmist lõpp-punkti:
http://api.nytimes.com/svc/search/v2/articlesearch
... artiklite toomiseks, mis on leitud kasutades valitud kuupäeva vahemikuga piiratud otsingupäringu terminit. Näiteks võiksime paluda API-l tagastada nimekiri kõigist New York Timesis ilmunud artiklitest, millel oli 2015. aasta juuli esimese seitsme päeva jooksul korvpalliga pistmist. Vastavalt API-le dokumentatsioon , selleks peame selle lõpp-punkti hankimise päringus määrama järgmised parameetrid:
Parameeter | Väärtus |
mida | “Korvpall” |
alguskuupäev | '20150701' |
end_date | '20150707' |
API vastus on üsna keeruline. Allpool on vastus päringule, mille ülaltoodud parameetrid piirduvad ainult ühe artikliga (üks element docs massiivis), selguse huvides on välja jäetud arvukad väljad.
{ '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.' }
Põhimõtteliselt saame vastuseks kolm valdkonda. Esimene helistas vastus sisaldab massiivi dokumendid , mis omakorda sisaldab artikleid esindavaid esemeid. Kaks teist välja on staatus ja autoriõigus . Nüüd, kui me teame, kuidas API töötab, on aeg luua Mantle'i abil andmemudelid.
Nagu varem mainitud, on Mantle avatud lähtekoodiga raamistik, mis lihtsustab oluliselt andmemudelite kirjutamist. Alustame artikliloendi päringu mudeli loomisega. Nimetagem seda klassi ArticleListRequestModel ja veenduge, et see pärineks MTLMudel , mis on klass, millest tuleks tuletada kõik Mantle'i mudelid. Lisaks muudame selle vastavusse MTLJSONSerialiseerimine protokoll. Meie taotlusmudelil peaks olema kolm sobivat tüüpi omadust: päring, articlesFromDate ja articlesToDate . Lihtsalt veendumaks, et meie projekt on hästi korraldatud, soovitan selle klassi panna Mudelid Grupp.
Mantle lihtsustab andmemudelite kirjutamist, vähendab katlakoodi koodi. PiiksumaSiit saate teada, kuidas ArticleListRequestModel peaks vaatama:
#import 'MTLModel.h' #import 'Mantle.h' @interface ArticleListRequestModel : MTLModel @property (nonatomic, copy) NSString *query; @property (nonatomic, copy) NSDate *articlesFromDate; @property (nonatomic, copy) NSDate *articlesToDate; @end
Kui otsime nüüd oma artikliotsingu lõpp-punkti dokumendid või vaatame ülaltoodud päringute parameetritega tabelit, märkame, et API-päringus olevate muutujate nimed erinevad meie päringumudeli nimedest. Mantle saab sellega tõhusalt hakkama, kasutades meetodit:
+ (NSDictionary *)JSONKeyPathsByPropertyKey.
Seda meetodit tuleks meie taotlusmudeli rakendamisel rakendada järgmiselt.
#import 'ArticleListRequestModel.h' @implementation ArticleListRequestModel #pragma mark - Mantle JSONKeyPathsByPropertyKey + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @'query': @'q', @'articlesFromDate': @'begin_date', @'articlesToDate': @'end_date' }; } @end
Selle meetodi rakendamine täpsustab, kuidas mudeli omadused vastendatakse selle JSON-i esitustesse. Kui meetod JSONKeyPathsByPropertyKey on rakendatud, saame mudeli JSON-sõnastiku esituse klassi meetodiga +[MTLJSONAdapter JSONArrayForModels:]
Nagu veel parameetrite loendist teada on, jääb alles see, et mõlemad kuupäeva parameetrid peavad olema vormingus „AAAAYMMDD”. Siin saab Mantle väga käepäraseks. Saame lisada mis tahes atribuudi kohandatud väärtuste teisenduse, rakendades valikulise meetodi +JSONTransformer
Selle rakendamisega räägime Mantle'ile, kuidas konkreetse JSON-välja väärtus tuleks JSON-i deserialiseerimise käigus muuta. Saame rakendada ka pöördtrafot, mida kasutatakse mudelist JSONi loomisel. Kuna me peame muutma NSDate objekti stringiks, kasutame ka seda NSDataFormatter klass. Siin on programmi täielik rakendamine ArticleListRequestModel klass:
#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
Mantle'i teine suurepärane omadus on see, et kõik need mudelid vastavad standardile NSC-kodeerimine protokolli, samuti rakendada isEqual ja räsi meetodid.
Nagu me juba nägime, sisaldab API-kõne tulemusel saadud JSON massiivi objekte, mis esindavad artikleid. Kui tahame seda vastust Mantle'i abil modelleerida, peame looma kaks eraldi andmemudelit. Modelleeriks artikleid esindavaid objekte ( dokumendid massiivi elemendid) ja teine modelleerib kogu JSON-i vastuse, välja arvatud docs-massiivi elemendid. Nüüd ei pea me kõiki sissetuleva JSON-i omadusi oma andmemudelitesse kaardistama. Oletame, et meid huvitavad ainult kaks artikliobjektide välja ja see oleks ka nii plii_osa ja web_url . The ArtikkelMudel klassi rakendamine on üsna lihtne, nagu näeme allpool.
#import 'MTLModel.h' #import @interface ArticleModel : MTLModel @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
Nüüd, kui artiklimudel on määratletud, saame vastusemudeli määratluse lõpetada, luues artikliloendi mudeli. Siit saate teada, kuidas klassi ArticleList vastusemudel välja näeb.
#import 'MTLModel.h' #import #import 'ArticleModel.h' @interface ArticleListResponseModel : MTLModel @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
Sellel klassil on ainult kaks omadust: staatus ja artiklid . Kui me võrdleme seda tulemusnäitaja vastusega, näeme, et kolmandat JSON-atribuudi autoriõigust vastuse mudelisse ei kaardistata. Kui vaatame artiklidJSONTrafo meetodi abil näeme, et see tagastab massiivi väärtustrafo klassi objekte sisaldava massiivi jaoks ArtikkelMudel .
Samuti väärib märkimist, et meetodis JSONKeyPathsByPropertyKey , mudeli omadus artiklid vastavad massiivi dokumentidele, mis on pesastatud JSON-atribuudi sisse vastus .
Nüüd peaks meil olema rakendatud kolm mudeliklassi: ArticleListRequestModel, ArticleModel ja ArticleListResponseModel.
Nüüd, kui oleme kõik andmemudelid juurutanud, on aeg klassi juurde naasta APIManager rakendada meetodit, mida kasutame GET-taotluste täitmiseks API-le. Meetod:
- (NSURLSessionDataTask *) getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure
võtab an ArticleListRequestModel päringu mudel parameetrina ja tagastab väärtuse ArticleListResponseModel edu või NSEvea korral muul viisil. Selle meetodi rakendamine kasutab AFVõrgustik API-le GET-päringu täitmiseks. Pange tähele, et eduka API-päringu esitamiseks peame esitama võtme, mille saab nagu eespool mainitud, registreerudes aadressil 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); }]; }
Selle meetodi rakendamisel toimub kaks väga olulist asja. Kõigepealt heidame pilgu sellele reale:
NSDictionary *parameters = [MTLJSONAdapter JSONDictionaryFromModel:requestModel error:nil];
Siin toimub see, et kasutades pakutavat meetodit MTLJSONAdapter klassi saame a NSSõnastik meie andmemudeli esitus. See esitus peegeldab API-le saadetavat JSON-i. Siin peitubki Mantle ilu. Pärast rakendamist JSONKeyPathsByPropertyKey ja +JSONTransformer
klassis ArticleListRequestModel, saame ühe andmereaga õige aja jooksul oma andmemudeli õige JSON-esituse.
Mantle võimaldab meil teha teisendusi ka teises suunas. Ja täpselt see juhtub API-lt saadud andmetega. Vastuvõetud NSDictionary sõnastatakse klassi ArticleListResponseModel objektiks järgmise klassi meetodi abil:
ArticleListResponseModel *list = [MTLJSONAdapter modelOfClass:ArticleListResponseModel.class fromJSONDictionary:responseDictionary error:&error];
Nüüd, kui oleme võimelised andmeid hankima kaug-API-st, on aeg neid jätkata. Nagu sissejuhatuses mainitud, teeme seda Realmi kasutades. Realm on mobiilne andmebaas ning põhiandmete ja SQLite'i asendaja. Nagu näeme allpool, on selle kasutamine äärmiselt lihtne.
Realm, ülim mobiilne andmebaas, on põhiandmete ja SQLite'i ideaalne asendaja. PiiksumaAndmebaasi reaalsusse salvestamiseks peame kõigepealt kapseldama objekti, mis on tuletatud klassist RLMObject. Nüüd peame looma mudeli klassi, mis salvestab üksikute artiklite andmeid. Siit saate teada, kui lihtne on sellise klassi loomine.
#import 'RLMObject.h' @interface ArticleRealm : RLMObject @property NSString *leadParagraph; @property NSString *url; @end
Ja see võiks põhimõtteliselt nii olla, selle klassi rakendamine võib jääda tühjaks. Pange tähele, et mudeliklassi omadustel pole selliseid atribuute nagu nonatoomiline, tugev või koopia. Valdkond hoolitseb nende eest ja me ei pea nende pärast muretsema.
Kuna artiklid, mida me saame, on modelleeritud Mante mudeliga Artikkel oleks mugav lähtestada ArtikkelRealm klassi objektidega objektid Artikkel . Selleks lisame initWithMantleModel meetodit meie Realmi mudeli järgi. Siin on rakenduse täielik rakendamine ArtikkelRealm klass.
#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
Me suhtleme andmebaasiga klassi objektide abil RLMRealm . Saame hõlpsasti a RLMRealm objekti, kasutades meetodit “[RLMRealm defaultRealm]”. Oluline on meeles pidada, et selline objekt kehtib ainult selles lõimes, millele see loodi, ja seda ei saa lõimede vahel jagada. Andmete kirjutamine Realmi on üsna lihtne. Kirjutustehingu raames tuleb teha üksik kirjutus või nende rida. Siin on andmebaasi kirjutamise näidis:
RLMRealm *realm = [RLMRealm defaultRealm]; ArticleRealm *articleRealm = [ArticleRealm new]; articleRealm.leadParagraph = @'abc'; articleRealm.url = @'sampleUrl'; [realm beginWriteTransaction]; [realm addObject:articleRealm]; [realm commitWriteTransaction];
Siin juhtub järgmine. Kõigepealt loome a RLMRealm objekt andmebaasiga suhtlemiseks. Siis an ArtikkelRealm mudeliobjekt on loodud (palun pidage meeles, et see pärineb RLMRealm klass). Lõpuks selle salvestamiseks algab kirjutamistehing, objekt lisatakse andmebaasi ja kui see on salvestatud, on kirjutamistehing sooritatud. Nagu näeme, blokeerivad kirjutamistehingud lõime, millele neid kutsutakse. Ehkki Realm on väidetavalt väga kiire, võib see lisada peamise lõime ühe tehingu raames andmebaasi mitu objekti, mis võib põhjustada kasutajaliidese reageerimise kuni tehingu lõpuleviimiseni. Loomulik lahendus on sellise kirjutustehingu sooritamine taustniidil.
See on kogu teave, mida vajame artiklite Realmi kasutamiseks. Proovime API-päringut täita meetodi abil
- (NSURLSessionDataTask *) getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure
ja Mantle'i taotluste ja vastuste mudelid, et saada New York Timesi artikleid, millel oli midagi pistmist (nagu varasemas näites) korvpalliga ja mis avaldati 2015. aasta juuni esimesel seitsmel päeval. Kui selliste artiklite loend on saadaval, jätkab seda ka Realmis. Allpool on kood, mis seda teeb. See on paigutatud viewDidLoad tabelivaate kontrolleri meetod meie rakenduses.
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]; }];
Esiteks tehakse API-kõne (2) päringumudeliga (1), mis tagastab vastusemudeli, mis sisaldab artiklite loendit. Nende artiklite püsimiseks Realm-i abil peame looma Realm-mudeli objektid, mis toimuvad for-silmus (4). Samuti on oluline tähele panna, et kuna ühe kirjutustehingu jooksul püsib mitu objekti, viiakse see kirjutustehing läbi taustniidile (3). Kui kõik artiklid on Realmi salvestatud, määrame need klassi atribuudile ise.artiklid (7). Kuna neile pääseb hiljem juurde TableView andmeallika meetodite põhilõigus, on ohutu neid hankida ka Reali andmebaasist peaniidil (5). Uuest lõimest andmebaasile juurde pääsemiseks tuleb sellel lõimel luua uus RLMRealmi objekt (6).
Kui API-lt uute artiklite hankimine mingil põhjusel ebaõnnestub, otsitakse olemasolevad tõrkeplokis olevast kohalikust salvestusruumist.
Selles õpetuses õppisime, kuidas seadistada kaugjuhtimispuldiga suhtlemiseks kakao ja kakao puute mudelraamistikku Mantle TULI . Samuti õppisime, kuidas Realmi mobiilse andmebaasi abil Mantle mudeli objektidena saadud andmeid lokaalselt säilitada.
Kui soovite seda rakendust proovida, saate lähtekoodi hankida selle GitHubi hoidla . Enne rakenduse käivitamist peate looma ja esitama oma API-võtme.