RestKit is een krachtige bibliotheek die de interactie met webservices voor iOS-applicaties vereenvoudigt. In dit artikel, geschreven door RestKit creator en Blake Watters van Two Toasters, zullen we een korte rondleiding geven over de feature set van RestKit, bekend raken met de kernconcepten van de bibliotheek en vervolgens enkele codevoorbeelden onderzoeken om een indruk te krijgen van wat werken met RestKit is echt zo.
RestKit is een Objective-C-framework voor iOS dat als doel heeft om interactie met RESTful-webservices eenvoudig, snel en leuk te maken. Het combineert een schone, eenvoudige HTTP-verzoek / reactie-API met een krachtig objecttoewijzingssysteem dat de hoeveelheid code vermindert die u moet schrijven om 'dingen gedaan te krijgen'. Het belangrijkste doel van RestKit is om de ontwikkelaar meer te laten nadenken over het datamodel van zijn toepassing en zich minder zorgen te maken over de details van verzendverzoeken, het parseren van reacties en het bouwen van representaties van bronnen op afstand.
RestKit is beschikbaar als een downloadbaar binair pakket, als een momentopname met versie of als een Git-submodule als u de ontwikkeling van de hoofdlijn wilt volgen. Voor gebruikers van de bibliotheek die niet geïnteresseerd zijn in het doen van ontwikkeling, raden we aan de binaire pakketten met versiebeheer te gebruiken voor de eenvoud van de installatie. Als u als submodule wilt installeren of de bibliotheek zelf wilt bouwen, raadpleegt u de documentatie die beschikbaar is op Github.
Je kunt RestKit in een paar eenvoudige stappen installeren:
Zoek nu het Andere Linker-vlaggen setting. Dubbelklik erop en voeg items toe voor -all_load en -ObjC. Uw instelling moet overeenkomen met de onderstaande schermafbeelding.
Sluit het inspectievenster.
Gefeliciteerd, je bent nu klaar met het toevoegen van RestKit aan je project!
U hoeft nu alleen maar onderdelen voor de RestKit-bibliotheken op de juiste plaatsen in uw toepassing toe te voegen. De relevante omvat zijn:
#importeren#importeren // Als u Core Data gebruikt?
Bouw het project om ervoor te zorgen dat alles correct werkt.
Zodra u hebt gecontroleerd dat RestKit op de juiste manier is gekoppeld aan uw project, bent u klaar om de bibliotheek te gaan gebruiken.
RestKit is ontworpen om algemene taken zo eenvoudig en eenvoudig mogelijk te maken. In deze sectie zullen we veel algemene taken in de bibliotheek doornemen en ons concentreren op codevoorbeelden om u te helpen aan de slag te gaan met de bibliotheek.
Alle functionaliteit op een hoger niveau van RestKit is bovenop de netwerklaag gebouwd. De primaire verantwoordelijkheid van de netwerklaag is de constructie en verzending van verzoeken en de verwerking van antwoorden. Over het algemeen verzendt u alle aanvragen via de klasse RKClient.
RKClient is een webclient-object dat is geconfigureerd om met een bepaalde webserver te communiceren. Het is geïnitialiseerd met een basis-URL en stelt u in staat om de configuratie in te stellen die gemeenschappelijk is voor de aanvragen in uw toepassing, zoals HTTP-headers en authenticatie-informatie. Hoewel u vrij bent om zoveel exemplaren van RKClient te initialiseren als geschikt is voor uw toepassing, is er een gedeelde singleton-instantie die wereldwijd beschikbaar is. Deze singleton-instantie wordt vaak geconfigureerd in de afgevaardigden van uw app applicationDidFinishLaunching: withOptions:
methode:
- (void) applicationDidFinishLaunching: (UIApplication *) toepassing met Opties: (NSDictionary *) opties RKClient * client = [RKClient clientWithBaseURL: @ "http://restkit.org"];
De eerste RKClient die is geïnitialiseerd, wordt automatisch geconfigureerd als de singleton-instantie en wordt beschikbaar via de sharedClient singleton-methode:
NSLog (@ "Ik ben jouw RKClient singleton:% @", [RKClient sharedClient]);
Nu u een client hebt geconfigureerd, kunt u HTTP-aanvragen verzenden en verwerken via de client. RestKit maakt dit heel gemakkelijk voor u en vat de details op laag niveau van NSURLConnection bij u weg. Wanneer u via de client een verzoek indient, levert u het resourcepad op de externe webserver waarmee u wilt communiceren. Omdat de meest voorkomende actie in een iOS-applicatie een asynchroon verzoek doet naar een externe webservice, biedt RestKit zeer eenvoudige eenvoudige methoden voor de HTTP-werkwoorden: GET, POST, PUT en DELETE. U hoeft alleen aan te geven dat uw klasse het RKRequestDelegate-protocol implementeert en vervolgens een implementatie van de aanvraag: didLoadResponse:
methode. Laten we een voorbeeldklasse bekijken die de basis laat zien:
#importeren// Hier verklaren we dat we het RKRequestDelegate-protocol // Checkout RestKit / Network / RKRequest.h implementeren voor extra gedelegeerde methoden // die beschikbaar zijn. @interface RKRequestVoorbeelden: NSObject @end @implementation RKRequestExamples - (void) sendRequests // Voer een eenvoudige HTTP GET uit en bel me terug met de resultaten [[RKClient shared Client] haal: @ "/ foo.xml" delegate: self]; // Stuur een POST naar een externe resource. Het woordenboek wordt op transparante wijze // geconverteerd naar een URL-gecodeerde weergave en verzonden als het verzoekorgaan. NSDictionary * params = [NSDictionary woordenboekWithObject: @ "RestKit" forKey: @ "Afzender"]; [[RKClient sharedClient] post: @ "/ other.json" params: params delegate: self]; // DELETE een externe bron van de server [[RKClient client] delete: @ "/ missing_resource.txt" delegate: self]; - (ongeldig) verzoek: (RKRequest *) verzoek didLoadResponse: (RKResponse *) antwoord if ([request isGET]) // Handling GET /foo.xml if ([response isOK]) // Succes! Laten we eens kijken naar de gegevens NSLog (@ "Retrieved XML:% @", [response bodyAsString]); else if ([request isPOST]) // Handling POST /other.json if ([response isJSON]) NSLog (@ "Heb een JSON-reactie terug van onze POST!"); else if ([request isDELETE]) // Handling DELETE /missing_resource.txt if ([response isNotFound]) NSLog (@ "Het resourcepad '% @' is niet gevonden.", [request resourcePath]); @end
Zoals u kunt zien, is de code uiterst beknopt en leesbaar. Er zijn een aantal hulpmethoden beschikbaar op RKRequest en RKResponse die het controleren van uw verzoekstaat zeer eenvoudig maken. Zorg ervoor dat u de headers leest en vertrouwd raakt met wat er beschikbaar is.
Het verzenden en ontvangen van HTTP-aanvragen met zo'n gemak is geweldig en alles, maar dat is nog maar het topje van de ijsberg. De echte kracht van RestKit komt niet van de netwerklaag, maar van de objectmapping-laag die er bovenop zit. Objecttoewijzing is de RestKit-oplossing voor het vereenvoudigen en opdrogen van de overdreven uitgebreide werkstroom van:
Net zoals RKClient uw poort naar een eenvoudiger leven met HTTP is, is RKObjectManager uw toegangspoort tot de wereld van het in kaart brengen van objecten. In feite wordt bij projecten waarbij objecttoewijzing uitgebreid wordt gebruikt, RKObjectManager in plaats van RKClient geïnitialiseerd. Net zoals RKClient de zanderige details van verwerkingsverzoeken wil wegstrepen, werkt RKObjectManager hard om u te beschermen tegen de complexiteit van het transformeren van gegevenspayloads naar objecten.
Voor objecttoewijzing moet u een gegevensmodelklasse opgeven om uw externe objecten te vertegenwoordigen. Door het RKObjectMappable-protocol te implementeren, configureert u RestKit om kenmerken binnen een opgehaalde payload toe te wijzen aan eigenschappen in uw modelles. De sleutel tot dit proces is de elementToPropertyMappings
methode, die een woordenboek met sleutelpaden en eigenschapnamen definieert. De sleutelpaden zijn coderingen die voldoen aan de sleutelwaarden voor het benaderen van gegevens in een geparseerd document. De eigenschapsnaam is gewoon de tekenreeksnaam van een eigenschap in de klasse om de toegang tot de gegevens toe te wijzen.
Om deze punten te illustreren, stellen we ons voor dat onze applicatie een lichtgewicht contactconcept heeft met een naam, een e-mailadres en een identificatienummer. Laten we ons voorstellen dat deze plaat op onze externe server woont / Contacten / 1234
. De JSON ziet er zo uit:
'id': 1234, 'name': 'Blake Watters', 'company': 'Two Toasters'
Laten we een RKObject-klasse samenstellen om deze gegevens te bevatten:
@interface Contact: RKObject NSNumber * _identifier; NSString * _name; NSString * _company; @property (nonatomic, retain) NSNumber * identifier; @property (nonatomic, retain) NSString * naam; @property (nonatomic, retain) NSString * bedrijf; @einde
Nu hoeven we RestKit alleen maar te vertellen hoe gegevens van de payload aan onze eigenschappen moeten worden toegewezen:
@implementation Contact - (NSDictionary *) elementToPropertyMappings retourneer [NSDictionary woordenboekWithKeysAndObjects: @ "id", @ "identifier", @ "name", @ "name", @ "company", @ "company", nihil]; @end
We zijn nu helemaal klaar om de gegevens te laden. Om dit te doen, stellen we RKObjectManager in en voeren we een GET uit op het record. RKObjectManager zal een asynchrone RKObjectLoader-aanvraag voor u samenstellen en configureren en deze naar de externe server verzenden voor verwerking. In plaats van de methoden voor laag niveau RKRequestDelegate te implementeren die zich bezighouden met verzoeken en antwoorden, implementeren we in plaats daarvan het RKObjectLoaderDelegate-protocol en worden we teruggebeld met een verzameling toegewezen objecten of een fout. Laten we deze code eens bekijken:
- (void) loadContact RKObjectManager * manager = [RKObjectManager objectManagerWithBaseURL: @ "http://restkit.org"]; [manager loadObjectsAtResourcePath: @ "/ contacts / 1" objectClass: [Contact class] delegate: self] // RKObjectLoaderDelegate methods - (void) objectLoader: (RKObjectLoader *) objectLoader didLoadObjects: (NSArray *) objecten Contact * contact = [ objecten objectAtIndex: 0]; NSLog (@ "Geladen Contact ID #% @ -> Naam:% @, Bedrijf:% @", contact.id, contact.name, contact.company); - (void) objectLoader: (RKObjectLoader *) objectLoader didFailWithError: (NSError *) error NSLog (@ "Encountered an error:% @", error);
Zoals u kunt zien, is het hele proces zeer laag ceremonieel en volledig droog.
Het laden van objecten is slechts de helft van het verhaal. Als u echt wilt communiceren met een externe webservice, moet u ook externe objectexemplaren kunnen maken, bijwerken en verwijderen. Een verstorende factor in deze interacties is vaak dat het resourcepad van een object specifiek is voor elke instantie. Terugkerend naar het bovenstaande contactvoorbeeld, stel je voor dat de hele wereld van contactpersonen wordt weergegeven door de volgende paren HTTP-werkwoorden en resourcepaden:
GET / contacten
retourneert alle contactpersonen als een verzamelingPOST / contacten
maakt een nieuw contact aanGET / contacten /
geeft een bepaalde contactgegevens terugPUT / contacten /
werkt een bestaande contactgegevens bijVERWIJDEREN / contacten /
verwijdert een bestaande contactpersoonOm rommelcodes met deze conventies en resourcepaden te voorkomen, biedt RestKit een routeringssysteem dat in staat is om resourcepaden voor een object te genereren. Routing is ontworpen als een uitbreidbaar systeem om flexibiliteit te bieden, maar RestKit wordt geleverd met een zeer capabele implementatie in de klasse RKDynamicRouter. Routering wordt ingeschakeld door een exemplaar van een object dat het RKRouter-protocol implementeert toe te wijzen aan de RKObjectManager en de router op de juiste manier te configureren. Laten we een voorbeeld bekijken van een configuratie met RKDynamicRouter en ons contactvoorbeeld:
RKDynamicRouter * router = [RKDynamicRouter nieuw]; // Definieer een standaardresourcepad voor alle niet-opgegeven HTTP-werkwoorden [router routeClass: [Contactklasse] toResourcePath: @ "/ contacts / (identifier)"]; [router routeClass: [Contact class] toResourcePath: @ "/ contacts" forMethod: RKRequestMethodPOST]; [RKObjectManager sharedManager] .router = router;
Het opmerkelijke stuk in de configuratie is het gebruik van haakjes in het resourcepad voor de standaardroute. Binnen de haakjes kunt u elke instantiemethode opgeven voor de klasse die wordt geconfigureerd en wanneer RestKit een resourcepad voor dat object genereert, wordt de geretourneerde waarde geïnterpoleerd naar de tekenreeks.
In ons voorbeeld hierboven kunnen we zien dat GET, PUT en DELETE operaties genereren / contacts / 1234 terwijl POST zal genereren / contacten.
Nu we de routering hebben geconfigureerd, kunnen we objecten op afstand op een zeer hoog niveau manipuleren. Laten we eens wat meer code bekijken en dan zullen we het proces doorlopen:
- (void) createObject Contact * joeBlow = [Contact object]; joeBlow.name = @ "Joe Blow"; joeBlow.company = @ "Two Toasters"; // POST to / contacts [[RKObjectManager sharedManager] postObject: joeBlow delegate: self]; - (void) updateObject Contact * blake = [Contact object]; blake.identifier = [NSNumber numberWithInt: 1]; blake.name = @ "Blake Watters"; blake.company = @ "RestKit"; // PUT naar / contacts / 1 [[RKObjectManager sharedManager] putObject: blake delegate: self]; - (void) deleteObject Contact * blake = [Contact object]; blake.identififer = [NSNumber numberWithInt: 1]; // DELETE to / contacts / 1 [[RKObjectManager sharedManager] deleteObject: blake delegate: self];
Wat we hier hebben gedaan, is de gecombineerde kracht van objecttoewijzing en routering gebruiken om manipulaties op zeer hoog niveau uit te voeren op lokale en externe objecten. Achter de schermen heeft RestKit het juiste resourcepad voor uw bewerking geïdentificeerd, een asynchroon verzoek gemaakt en verzonden en het antwoord voor u verwerkt.
Client en Object Manager. Er zijn twee primaire toegangspunten voor het werken met RestKit in uw toepassing: RKClient en RKObjectManager. RKClient is het primaire toegangspunt wanneer je werkt met de netwerklaag van RestKit en houdt zich bezig met de lage details van de bouw- en verzendingsverzoeken. RKObjectManager werkt op een hoger niveau van abstractie in de laag Object Mapping en houdt zich bezig met het laden en manipuleren van objecten die bronnen op afstand vertegenwoordigen. Afhankelijk van wat u met RestKit probeert te bereiken, zult u uitgebreid met één (of beide!) Van deze klassen werken.
Basis-URL's en bronpaden. RestKit gebruikt de concepten van de 'Base-URL' en 'Resource-pad' om de toegang tot externe objectrepresentaties te coördineren. De basis-URL is eenvoudigweg het gemeenschappelijke deel van alle URL's naar uw externe toepassing en wordt gebruikt om instanties van de klassen RKClient en RKObjectManager te initialiseren. Een resourcepad is gewoon het pad (of subpad) van de volledige URL naar een HTTP-bron. Gegeven een RKClient-object dat is geïnitialiseerd met 'http://restkit.org' en een verzoek om de inhoud op het resourcepad '/foo/bar.json' TE KRIJGEN, maakt RestKit een verzoek naar 'http://restkit.org' /foo/bar.json'. Op deze manier kunt u gemakkelijk ontwikkel-, staging- en productieomgevingen in uw toepassingen ondersteunen door verschillende basis-URL's voorwaardelijk te compileren. Meestal zult u volledig denken in termen van resourcepaden zodra u verder bent gegaan dan het initialiseren van de bibliotheek.
Voorbeeld:
RKClient * client = [RKClient clientWithBaseURL: @ "http: ///restkit.org"]; [client get: @ "/ foo / bar.json" delegate: self];
Voorbeeld:
@implementation MyObject // Map full_name en street_adddress in JSON payload naar // local properties fullName en streetAddress + (NSDictionary *) elementToPropertyMappings retourneer [NSDictionary woordenboekWithKeysAndObjects: @ "full_name", @ "fullName", @ "street_address", @ "streetAddress ", nul]; @end
Voorbeeld:
RKObjectManager * manager = [RKObjectManager objectManagerWithBaseURL: @ "http://restkit.org"]; RKDynamicRouter * router = [[RKDynamicRouter nieuw] autorelease]; manager.router = router; // Verzend POST-verzoeken voor instanties van Artikel naar '/ artikelen' [routerrouteClass: [Artikelklasse] toResourcePath: @ "/ articles" forMethod: RKRequestMethodPOST]; // Een standaardresourcepad voor artikelen configureren. GET, PUT en DELETE-verzoeken verzenden naar '/ articles / XXXX' // articleID is een eigenschap in de artikelklasse [routerrouteClass: [Article class] toResourcePath: @ "/ articles / (articleID)"]; // Stel reacties op het artikel in. Verzend POST van commentaarobjecten naar '/ articles / 1234 / comments' // waarbij de opmerking een relatie heeft met een artikel. [router routeClass: [Commentaar klasse] toResourcePath: @ "/ articles / (article.articleID) / comments" forMethod: RKRequestMethodPOST]; // Laten we een Article Article * article = [Artikel object] maken; article.title = @ "Foo"; article.body = @ "Dit is het lichaam"; // Stuur een POST naar / artikelen om de externe instantie te maken [[RKObjectManager sharedManager] postObject: article delegate: self]; // Laten we nu een opmerking maken over de artikelcommentaar * comment = [Commentaarobject]; comment.article = artikel; comment.body = @ "Dit is de opmerking!"; // Gegeven artikel heeft een ID van 1234, stuurt een POST naar / articles / 1234 / comments om de opmerking te maken [[RKObjectManager sharedManager] postObject: comment delegate: self]; // Verwijder het artikel. DELETE naar / articles / 1234 [[RKObjectManager sharedManager] deleteObject: comment delegate: self];
Dit artikel heeft de basis van het werken met RestKit onderzocht. Je moet nu een goed begrip hebben van de basisbegrippen en je goed voorbereid voelen om te beginnen met het bouwen van je volgende RESTful iOS-app. Zoals we in het inleidende gedeelte al vermeldden, bevat RestKit ook enkele geavanceerde functies die in dit artikel niet zijn onderzocht. We zullen de geavanceerde delen van de bibliotheek inclusief Core Data volledig verkennen in onze aankomende geavanceerde tutorial. Tot die tijd kunt u meer informatie krijgen via de voorbeeldcode die bij de bibliotheek is geleverd en door de onderstaande bronnen te verkennen.