Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Mobile Development

Neben die Grundlagen von JSONModel

by
Read Time:16 minsLanguages:

German (Deutsch) translation by Federicco Ancie (you can also view the original English article)

In meinem vorherigen Artikel haben Sie die Grundlagen von JSONModel kennengelernt. Sie haben gesehen, wie einfach es ist, mit JSON mit JSONModel zu arbeiten, und wie viel es hinter den Kulissen für Sie tut, z. B. Datenvalidierung und -konvertierung.

In diesem Lernprogramm erstellen Sie eine komplexere Anwendung und lernen eine Reihe von Funktionen kennen, die Ihren Modellklassen noch mehr Leistung verleihen.

Am Ende dieses Artikels haben Sie einen Flickr-Browser für iOS erstellt. Die Anwendung kommuniziert mit der JSON-API von Flickr und zeigt eine Sammlung von Fotos an, die ich für dieses Tutorial auf Flickr hochgeladen habe.

Sie werden lernen:

  • komplexe API-Antworten verarbeiten
  • Вie Datentransformationen von JSONModel für URLs und Datumsangaben verwenden
  • JSON-Schlüssel Eigenschaften mit unterschiedlichen Namen zuordnen
  • Benutzerdefinierte Datenkonvertierungen erstellen
  • API-Antworten vorverarbeiten, bevor sie analysiert werden

Der fertige Flickr-Browser sieht folgendermaßen aus:

1. Projekteinrichtung

Da wir uns darauf konzentrieren werden, die Funktionen von JSONModel kennenzulernen, möchte ich mit einem Vorsprung beginnen, indem ich mit einem Basisprojekt beginne. Sie finden das Projekt in den Quelldateien dieses Tutorials.

Öffnen Sie das Xcode-Projekt und nehmen Sie sich einen Moment Zeit, um dessen Inhalt zu überprüfen. Das Projekt hat eine einfache Einrichtung, eine einzelne Tabellenansicht, die eine leere Tabellenansicht anzeigt. Ich habe auch zwei Bibliotheken in das Projekt aufgenommen, JSONModel und SDWebImage.

Erstellen Sie das Projekt und führen Sie es aus, um sicherzustellen, dass das Projekt fehlerfrei kompiliert wird.

2. Antwortmodell

Werfen wir einen Blick auf den öffentlichen Foto-Feed von Flickr. Öffnen Sie den API-Endpunkt in Ihrem Browser und nehmen Sie sich einen Moment Zeit, um die Antwort zu überprüfen. Die Antwort enthält nur einige Schlüssel der obersten Ebene, z. B. title und modified. Es gibt auch einen Schlüssel namens items, der eine Liste von Fotoobjekten mit title, link, description usw. enthält.

Im folgenden Screenshot habe ich eines dieser Fotoobjekte im items array hervorgehoben, um Ihnen zu helfen, seine Eigenschaften herauszufinden.

Beginnen wir mit der Erstellung einer Modellklasse für die Antwort des öffentlichen Foto-Feeds. Erstellen Sie eine neue Klasse in Xcode, nennen Sie sie PublicPhotosModel und erben Sie sie von JSONModel. Sie interessieren sich für den title und die modified Schlüssel der JSON-Antwort. Fügen Sie daher der Schnittstelle der PublicPhotoModel-Klasse zwei gleichnamige Eigenschaften hinzu. Sie rufen auch das Array von Fotos ab und speichern sie in einer Eigenschaft, in der wir items benennen. Setzen Sie den Typ der Eigenschaft items wie unten gezeigt auf NSArray.

In diesem Beispiel verwenden Sie einen der integrierten Datentransformatoren von JSONModel. Wenn Ihre JSON-Antwort ein Datum enthält, das dem W3C-Format entspricht, können Sie die übereinstimmende Modelleigenschaft vom Typ NSDate deklarieren, und JSONModel weiß, was zu tun ist.

Ihre grundlegende Modellklasse zum Abrufen von JSON-Daten von der Flickr-API ist bereit. Verbinden wir es mit der Tabellenansicht in Ihrem View Controller. Sie verwenden das items array in Ihrem Modellobjekt, das die Antwort der Flickr-API darstellt, als Datenquelle für die Tabellenansicht.

Hinweis: Möglicherweise fragen Sie sich, wie Datumsangaben konvertiert werden sollen, wenn sie nicht dem W3C-Standard entsprechen oder wenn die JSON-Antwort Zeitstempel enthält. Weiter lesen. Vor dem Ende dieses Tutorials erfahren Sie, wie Sie einen beliebigen Wert in ein Objective-C-Objekt umwandeln.

3. Abrufen von JSON von der Flickr-API

Öffnen Sie zunächst ViewController.m und fügen Sie unter der vorhandenen Importanweisung eine Importanweisung für die gerade erstellte Modellklasse hinzu:

Deklarieren Sie als Nächstes eine private Eigenschaft zum Speichern der von uns verwendeten PublicPhotosModel-Instanz:

Sie rufen die JSON-Daten mit der Hilfsmethode fetchPhotos ab, die wir in Kürze implementieren werden. Wir rufen fetchPhotos in der viewDidLoad-Methode des View Controllers auf:

In fetchPhotos verwenden wir die NSURLSession-Klasse, um die Flickr-API abzufragen, wie Sie unten sehen können:

Die Implementierung ist ziemlich ähnlich zu dem, was Sie im vorherigen Artikel über JSONModel geschrieben haben. Sie deklarieren zuerst photosURL, die die URL eines bestimmten Feed von Fotos auf Flickr enthält, und erstellen und feuern dann eine NSURLSessionDataTask-Instanz, um die Liste der Fotos dieses Feeds abzurufen.

Hinweis: Wenn Sie ein Flickr-Konto haben und Ihre Flickr-ID kennen, können Sie diese in die Anforderungs-URL aufnehmen, damit die Anwendung Ihren eigenen Feed mit Fotos abruft.

Wenn Sie den ersten Artikel über JSONModel gelesen haben, wissen Sie bereits, wie Sie das von der Datenaufgabe zurückgegebene NSData-Objekt in ein JSONModel-Objekt umwandeln. Flickr gibt jedoch nicht immer eine gültige JSON-Antwort zurück. Mit anderen Worten, Sie müssen einige Vorverarbeitungen durchführen, bevor Sie Ihr Modellobjekt erstellen.

Die Flickr-API verfügt über eine spezielle Funktion, die einfache Anführungszeichen in der JSON-Antwort umgeht. Das Problem ist, dass dadurch die JSON-Antwort gemäß den aktuellen Standards ungültig wird und die NSJSONSerialization-API sie daher nicht verarbeiten kann.

Um dies zu beheben, müssen Sie nur die maskierten einfachen Anführungszeichen in der JSON-Antwort entfernen. Sie können dann Ihr Modellobjekt sicher erstellen. Ersetzen // Process Data durch das folgende Snippet:

Sie erstellen zunächst ein NSString-Objekt aus der NSData-Instanz, die die Datenaufgabe an Sie zurückgibt. Es ist sicher anzunehmen, dass der Text UTF8-codiert ist, da Flickr nur UTF8 verwendet. Anschließend ersetzen Sie alle Vorkommen von \' durch ', um die JSON-Antwort für JSONModel vorzubereiten.

Da Sie die JSON-Antwort bereits als Zeichenfolgenobjekt haben, können Sie den benutzerdefinierten JSONModel-Initialisierer initWithString:error: verwenden, um die Modellinstanz zu erstellen. Sie verwenden GCD, um die Benutzeroberfläche im Hauptthread zu aktualisieren. Der Titel des Ansichtscontrollers wird mit der title-Eigenschaft der PublicPhotosModel-Instanz aktualisiert und die Tabellenansicht wird neu geladen.

Erstellen Sie das Projekt und führen Sie es aus, um zu überprüfen, ob der Titel festgelegt ist. Dies zeigt an, dass das Modellobjekt ordnungsgemäß initialisiert wurde. Geben Sie der Anwendung einen Moment Zeit, um die JSON-Daten von der Flickr-API abzurufen. Sie sollten dann den Titel des Feeds oben auf dem Bildschirm sehen:

Wenn der Titel des Feeds aus irgendeinem Grund nicht wie im obigen Screenshot angezeigt wird, fügen Sie im Abschlusshandler der Datenaufgabe eine Protokollanweisung hinzu, um das Problem zu beheben. Wenn Sie überprüfen möchten, ob beim Erstellen des Modellobjekts ein Fehler aufgetreten ist, aktualisieren Sie die Initialisierung des Modellobjekts:

Wie Sie sehen können, verwendet JSONModel das Standardparadigma der Cocoa-Fehlerbehandlung. Dies bedeutet, dass Sie überprüfen können, ob initWithString:error: einen Fehler auslöst.

4. Implementieren Sie die Tabellenansicht

Derzeit behandelt JSONModel das Array von Elementen als normales Array, das NSDictionary-Objekte enthält. Dies ist vorerst in Ordnung, aber wir werden später in diesem Tutorial ein geeignetes Fotomodell erstellen. Es ist Zeit, die Tabellenansicht mit den Elementen im Array zu füllen.

Beginnen wir mit der Erstellung der Benutzeroberfläche. Zunächst legen Sie den Titel der Kopfzeile des Tabellenansichtsabschnitts fest, in dem das Datum der letzten Änderung des Flickr-Feeds angezeigt wird. Sie können eine NSDateFormatter-Instanz verwenden, um das NSDate-Objekt in eine lesbare Zeichenfolge zu konvertieren und von zurückzugeben tableView:titleForHeaderInSection::

Fügen Sie als Nächstes die beiden erforderlichen Methoden des Datenquellenprotokolls für die Tabellenansicht hinzu, um der Tabellenansicht mitzuteilen, wie viele Abschnitte und Zeilen sie enthält. Verwenden Sie self.publicPhotos.items als Datenquelle für die Tabellenansicht:

Da die Bildansicht der UITableViewCell-Klasse Remotebilder nicht asynchron lädt, benötigen Sie eine benutzerdefinierte UITableViewCell-Unterklasse. Erstellen Sie eine neue Objective-C-Klasse, nennen Sie sie ImageCell und machen Sie sie zu einer Unterklasse von UITableViewCell. Öffnen Sie ImageCell.h und fügen Sie eine Eigenschaft vom Typ UIImageView, webImageView hinzu:

Öffnen Sie ImageCell.m und überschreiben Sie den dort eingegebenen Initialisierungs-Xcode. In initWithStyle: müssen Sie die Standardbildansicht ausblenden und eine neue benutzerdefinierte Bildansicht erstellen. Ob Sie es glauben oder nicht, aber genau das ist erforderlich, um Bilder asynchron in eine Tabellenansichtszelle zu laden.

Sind Sie von der zweiten Hälfte der Implementierung verwirrt? Sie erstellen ein leeres Bild mit einer Größe von 20 x 20 Pixel und legen es als Bild für die Standardbildansicht der Zelle fest. Sie tun dies, um die Textbeschriftung der Zelle richtig zu positionieren. Dies geschieht noch bevor das Bild für Ihre benutzerdefinierte Bildansicht aus dem Web geladen wird.

Besuchen Sie ViewController.m erneut und fügen Sie unter den vorhandenen Importanweisungen eine Importanweisung für die von uns erstellte benutzerdefinierte UITableViewCell-Klasse hinzu.

Sie sind bereit für das letzte Puzzleteil, die Datenquellenmethode zum Erstellen der Zellen für Ihre Tabelle:

Erstellen Sie das Projekt und führen Sie es noch einmal aus, um festzustellen, dass in der Tabelle jetzt eine Zelle für jedes der in items gefundenen Objekte angezeigt wird. Apropos Artikel, es ist items, das Fotomodell zu erstellen.

5. Fotomodell

Wie wir im vorherigen Lernprogramm gesehen haben, müssen Sie eine separate Modellklasse für eine Liste von Objekten in der JSON-Antwort erstellen, die Liste der Fotoelemente in unserem Beispiel. Erstellen Sie eine neue Objective-C-Klasse, nennen Sie sie PhotoModel und machen Sie sie zu einer Unterklasse von JSONModel.

Sehen Sie sich noch einmal die unformatierte JSON-Antwort an, die Sie von der Flickr-API erhalten, und entscheiden Sie, welche Schlüssel jedes Fotoobjekt haben muss:

Sie möchten den Titel, die URL des Fotos zum Zeitpunkt der Veröffentlichung und den Link zur Detailseite auf Flickr abrufen. Wir haben jedoch ein Problem. Die URL des Fotos ist in einem weiteren Objekt unter dem media schlüssel enthalten. Bedeutet dies, dass Sie nur eine weitere JSONModel-Unterklasse erstellen müssen, um den einzelnen Schlüssel m zu extrahieren, der die URL des Fotos enthält?

Zum Glück lautet die kurze Antwort nein. Um dieses Problem elegant zu lösen, müssen Sie lernen und verstehen, wie die Schlüsselzuordnung in JSONModel funktioniert. Das Zuordnen von Schlüsseln ist eine einfache Möglichkeit, Ihre JSONModel-Unterklasse anzuweisen, wie Daten aus einer JSON-Antwort extrahiert werden. Dies ist besonders nützlich, wenn die JSON-Schlüssel nicht genau mit den Namen der Eigenschaften Ihrer Klasse übereinstimmen.

Deklarieren Sie zunächst die Eigenschaften, die wir in der PhotoModel-Klasse benötigen:

Wir verwenden zwei der integrierten Datentransformatoren von JSONModel. Das published ist vom Typ NSDate und JSONModel stellt sicher, dass das W3C-Datum in ein NSDate-Objekt konvertiert wird. Die url- und link eigenschaften sind vom Typ NSURL, und JSONModel konvertiert die entsprechenden Zeichenfolgen der JSON-Antwort in NSURL-Objekte.

Öffnen Sie PhotoModel.m und fügen Sie das folgende Codefragment hinzu, um die Schlüsselzuordnung für das Fotomodell einzurichten:

In keyMapper überschreiben Sie die keyMapper-Methode von JSONModel. Es gibt eine JSONKeyMapper-Instanz zurück, das Objekt, das JSON-Schlüssel Eigenschaftsnamen zuordnet. Die JSONKeyMapper-Klasse verfügt über einen praktischen Initialisierer, der ein Wörterbuch akzeptiert und eine Schlüsselzuordnung zwischen den JSON-Daten und Ihrer Klasse erstellt.

In der obigen Implementierung von keyMapper definieren Sie die folgende Schlüsselzuordnung:

  • Der published Schlüssel in der JSON-Antwort wird der date eigenschaft des Modells zugeordnet.
  • Der m-Schlüssel des media objekts in der JSON-Antwort wird der url im Modell zugeordnet.

Wenn keyMapper implementiert ist, kann JSONModel die JSON-Antwort analysieren und das Fotomodell gemäß der Definition in der PhotoModel-Klasse initialisieren.

Öffnen Sie PhotoModel.h erneut, und deklarieren Sie oben ein Protokoll mit demselben Namen wie der Name der Klasse:

6. Anzeigen des Foto-Feeds

Wechseln Sie zu PublicPhotoModel.h und fügen Sie oben eine Importanweisung hinzu:

Damit dies alles funktioniert, muss die Eigenschaft items dem PhotoModel-Protokoll entsprechen, das wir vor kurzem in der PhotoModel-Klasse deklariert haben:

Sie müssen jetzt einige Anpassungen in Ihrer ViewController-Klasse vornehmen. Um Fotos in die Zellen Ihrer Tabellenansicht zu laden und anzuzeigen, verwenden Sie eine in der SDWebImage-Bibliothek deklarierte Methode, die in dem Projekt enthalten war, mit dem Sie begonnen haben. Öffnen Sie ViewController.m und fügen Sie oben eine neue Importanweisung hinzu:

Überprüfen Sie als Nächstes Ihre Implementierung von tableView:cellForRowAtIndexPath:, in der Sie derzeit nur die Zeilennummer anzeigen. Da Sie jetzt jedoch das entsprechende PhotoModel-Objekt für jede Zeile in der Tabellenansicht abrufen können, ist es besser, stattdessen die Details des Fotos anzuzeigen. Aktualisieren Sie die Implementierung wie folgt:

Sie rufen zuerst das PhotoModel-Objekt ab, das der Zeile in der Tabellenansicht entspricht, und füllen dann die Textbezeichnung der Zelle mit dem Titel des Fotos. Mit setImageWithURL:placeholderImage: von SDWebImage können Sie das Foto unter der angegebenen URL asynchron laden und anzeigen.

Ob Sie es glauben oder nicht, Sie haben bereits einen funktionierenden Fotostream. Erstellen Sie das Projekt und führen Sie es aus, um das Ergebnis anzuzeigen:

7. Benutzerdefinierte Datentransformationen

In diesem Abschnitt erstellen Sie eine benutzerdefinierte Funktion für die PhotoModel-Klasse, mit der eine Zeichenfolge aus der JSON-Antwort in eine benutzerdefinierte Objective-C-Klasse konvertiert wird. Hier erfahren Sie, wie Sie JSON-Daten in eine beliebige Objective-C-Klasse konvertieren.

In den JSON-Daten für ein Foto befindet sich ein Tag-Schlüssel, der eine Reihe von Tags enthält. Sie fügen der PhotoModel-Klasse eine neue Eigenschaft hinzu. Der Typ dieser Eigenschaft ist eine benutzerdefinierte Objective-C-Klasse, die Tags verarbeiten kann.

Hinweis: Sie können JSON-Daten nicht in benutzerdefinierte Objective-C-Klassen konvertieren. Sie können JSON-Daten in jede Cocoa-Klasse konvertieren. Beispielsweise können Sie eine Hex-Farbe wie #cc0033 in ihre UIColor-Entsprechung konvertieren. Lesen Sie weiter, um zu sehen, wie das geht.

Erstellen Sie eine neue Klasse, nennen Sie sie Tags und machen Sie sie zu einer Unterklasse von NSObject. Öffnen Sie Tags.h und fügen Sie eine Eigenschaft hinzu, um die Liste der Tags zu speichern und einen benutzerdefinierten Initialisierer zu deklarieren:

Wechseln Sie zu Tags.m und implementieren Sie den soeben deklarierten Initialisierer. Wie Sie sehen, ist daran nichts Besonderes. Mit der Zeichenfolge erstellen Sie ein Array von Tags und speichern die Tags in tags:

Sie haben jetzt eine benutzerdefinierte Tags-Klasse, aber wie verwenden Sie sie in Ihrem Fotomodell? Öffnen Sie PhotoModel.h, importieren Sie die neue Klasse oben und deklarieren Sie eine neue Eigenschaft in der Benutzeroberfläche der Klasse:

Erstellen und führen Sie Ihr Projekt so aus, wie es ist, um zu sehen, was passieren wird.

Da die Eigenschaft tags vom Typ Tags ist, mit dem JSONModel nicht umgehen kann, stürzt die Anwendung ab und in der XCode-Konsole sollte die folgende Fehlermeldung angezeigt werden:

Es ist Zeit, sich mit einer neuen Klasse der JSONModel-Bibliothek, der JSONValueTransformer-Klasse, vertraut zu machen. In den meisten Fällen arbeitet der JSONValueTransformer hinter den Kulissen und konvertiert grundlegende Datentypen für Sie, NSNumber in einen float, NSString in NSNumber oder NSString in NSDate. Die Klasse kann jedoch nicht mit benutzerdefinierten Klassen umgehen, da sie nicht weiß, wie sie damit arbeiten soll.

Das Schöne an JSONValueTransformer ist, dass Sie es erweitern können, um zu lernen, wie man mit benutzerdefinierten Klassen umgeht - oder mit jeder anderen Cocoa-Klasse.

Wählen Sie im Menü Datei von Xcode Neu > Datei... und in der Liste der Vorlagen die Kategorie Ziel-C. Klicke weiter um fortzufahren.

Benennen Sie die Kategorie Tags und setzen Sie Category On auf JSONValueTransformer. Klicken Sie weiter um fortzufahren.

In dieser Kategorie in JSONValueTransformer können Sie die erforderlichen Methoden für die Behandlung von Eigenschaften vom Typ Tags definieren. Öffnen Sie JSONValueTransformer+Tags.h und importieren Sie die Header-Datei der Tags-Klasse. Fügen Sie als Nächstes die folgenden zwei Methoden zur Schnittstelle der Kategorie hinzu:

Schauen wir uns die Namen dieser Methoden genauer an.

  • TagsFromNSString: Besteht aus dem Namen der Klasse oder des Typs, in den Sie konvertieren möchten, Tags, gefolgt von From und dem Typ in den JSON-Daten für den jeweiligen Schlüssel NSString. Kurz gesagt, wenn JSONModel eine Eigenschaft vom Typ Tags findet, wird versucht, einen JSON-Schlüssel vom Typ NSString abzugleichen. Wenn eine Übereinstimmung gefunden wird, wird TagsFromNSString: aufgerufen.
  • JSONObjectFromTags: Behandelt die umgekehrte Konvertierung. Wenn JSONModel Ihr Modellobjekt zurück in JSON-Daten exportiert, muss es eine Methode aufrufen, die das Tags-Objekt übernimmt und eine richtige Zeichenfolge zurückgibt. Daher lautet der Name der Methode JSONObjectFrom, gefolgt vom Namen der Klasse oder des Typs der Eigenschaft Tags.

Sobald Sie diese beiden Methoden definiert haben, kann jede JSONModel-Unterklasse Objekte vom Typ Tags verarbeiten. Das Hinzufügen einer Kategorie zu JSONValueTransformer ist eine sehr einfache Möglichkeit, den Modellklassen Ihrer Anwendung Funktionen hinzuzufügen.

Lassen Sie uns nun die Implementierung der beiden Methoden in unserer Kategorie untersuchen. Implementieren wir zunächst die Methode, die ein NSString-Objekt akzeptiert und ein Tags-Objekt zurückgibt:

Dank des benutzerdefinierten Initialisierers initWithString: ist die Implementierung einfach. Es nimmt die Zeichenfolge von Tags aus den JSON-Daten und gibt ein Tags-Objekt zurück, das Ihrer tags-Eigenschaft in der PhotoModel-Klasse zugewiesen ist.

Implementieren Sie als Nächstes die zweite Methode, die aufgerufen wird, wenn das Modellobjekt in eine Zeichenfolge konvertiert wird. Dies ist die Methode, die aufgerufen wird, wenn Sie toDictionary und toJSON von JSONModel aufrufen.

Wenn eine PublicPhotosModel-Instanz initialisiert wird, werden automatisch PhotoModel-Objekte erstellt und in der Eigenschaft items gespeichert. Jedes PhotoModel-Objekt erstellt außerdem ein Tags-Objekt für seine tags-Eigenschaft. All dies geschieht automatisch dank der Kategorie, die wir in JSONValueTransformer erstellt haben.

Verwenden wir jetzt die Eigenschaft tags in der PhotoModel-Klasse. Öffnen Sie ViewController.m und aktualisieren Sie die Implementierung von tableView:cellForRowAtIndexPath: indem Sie die Detailtextbeschriftung der Zelle mit der Liste der Tags des Fotos füllen.

Erstellen Sie das Projekt und führen Sie es aus. Sie sollten die Tags jedes Fotos sehen, die unter dem Titel des Fotos aufgeführt sind.

Um unseren Flickr-Browser zu vervollständigen, implementieren Sie tableView:didSelectRowAtIndexPath: des UITableViewDelegate-Protokolls. In tableView:didSelectRowAtIndexPath: rufen wir das entsprechende Foto ab und öffnen die Detailseite des Fotos in Safari.

Wenn Sie in der Tabellenansicht auf eine Zeile tippen, werden Sie zur Detailseite des Fotos auf Flickr weitergeleitet:

Abschluss

In diesem Lernprogramm haben Sie komplexere und leistungsfähigere Funktionen der JSONModel-Bibliothek verwendet. Ich hoffe, Sie können sehen, wie zeitsparend JSONModel sein kann und wie es Ihnen auf vielen Ebenen in Ihren iOS- und OS X-Projekten helfen kann. Wenn Sie mehr über JSONModel erfahren möchten, empfehlen wir Ihnen, die Dokumentation der Bibliothek zu lesen.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.