App-Programmierung für iOS und Android mit ReactNative

Einmal JavaScript-Code schreiben und Apps mit nativen Elementen für iOS und Android erhalten. Mit Facebook’s ReactNative können Software-Entwickler, die Erfahrungen mit nativer App-Programmierung haben, zügig eine einfache App für die aktuellen Hauptplattformen entwickeln und in den Apple App-Store sowie GooglePlay Store bringen.

Was ist ReactNative?

Mit ReactNative lassen sich iOS- und Android-Apps programmieren, die native Elemente verwenden und sich somit nicht von nativ programmierten Apps unterscheiden. Der Code wird nur einmal geschrieben, das Ergebnis ist eine App für iOS-Geräte und eine App für Android-Geräte.

ReactNative ist somit in keiner Weise mit Cordova oder ähnlichen Javascript-Frameworks vergleichbar, da diese lediglich Websites in einem Container sind. Native iOS- oder Android-Elemente kommen eigentlich nicht vor.

Bei ReactNative ist das anders. Das Framework von Facebook benutzt JavaScript und React, um native Elemente miteinander zu verbinden. Geschrieben wird der Code in JSX, einer Erweiterung basierend auf JavaScript und direkt in JavaScript. Hierbei wird die JavaScript-Syntax nach der ECMAScript-6-Norm verwendet. ReactNative-Apps laufen auf Geräten ab iOS 8 und Android 4.1.

Render-Funktion des Frameworks ReactNative zur App-Programmierung
Render-Funktion ReactNative

Im Beispiel sieht man die Render-Funktion einer klassischen ReactNative-Component. Zurückgegeben wird eine gestylte „View“, die als Subview ein „Text“-Element beinhaltet. Das „Text“-Element enthält einen Text und die Variable „name“, die von außen gesetzt wird.

Wie auch „View“ hat „Text“ die Property „style“. Mit „style“ lassen sich UI-Elemente Gestalten und Positionen. Das Naming ist ähnlich zu CSS. Will man Elemente in Abhängigkeit zu anderen Elementen positionieren, benutzt man flex, flex-direction und Ähnliches.

Benutzt man wie im Beispiel den Tag „Text“, wird im Hintergrund eine UILabel (iOS) bzw. eine TextView (Android) genutzt. Der „View“-Tag wird zu UIView bzw. zu einer nativen (Android-)View. Viele dieser Elemente oder auch Components genannt, liefert ReactNative standardmäßig und können ohne zusätzliche Installationen benutzt werden. Oftmals findet man in der npm-Library Erweiterungen zu bestehenden Components oder auch ganz neue, praktische Components. Möchte man eine native Component in ReactNative, die noch nicht verfügbar ist oder bestehenden nativen Code nutzen, muss man zuerst ein natives Bridging-Modul erstellen. Hierfür wird aber erweitertes Wissen in nativer App-Entwicklung für die jeweilige Plattform vorausgesetzt.

Was sind die Voraussetzungen für die App-Programmierung ReactNative?

Will man „nur“ Apps programmieren und sich nicht um das Drumherum (Veröffentlichung, Testphasen, etc.) kümmern, sollte man ein solides Wissen rund um JavaScript und das grundlegende Verständnis für den Aufbau einer App (ViewController, Daten-Handling, etc.) mitbringen.

Außerdem sollte man wissen, wie man mit dem Terminal umgeht, da ein großer Anteil bei der Einrichtung eines Projekts über die Console getätigt wird.

Gehen die Anforderungen über das Programmieren hinaus, sind vor allem auf iOS-Seite Erfahrungen rund um Zertifikate, Provisioning-Profiles und iTunesConnect erforderlich, da es sonst an der Veröffentlichung der App scheitern wird. Mit Android geht es vergleichsweise einfach, da es hierbei mit einigen Terminal-Eingaben und einem Google-Account oftmals getan ist.

Wann macht ReactNative Sinn?

Eine pauschale Antwort auf diese Frage gibt es nicht.

Beherrscht man zum Beispiel die native App-Programmierung für Android und kennt sich mit iOS weniger aus, macht eine ReactNative-App vielleicht mehr Sinn, als sich Swift oder Objective-C beizubringen. Das selbe gilt natürlich auch andersrum. Ist diese App allerdings so umfangreich, dass man nur wenige Codezeilen gemeinsam verwenden kann und somit viel mit Bridging-Modulen arbeiten muss, ist die native Programmierung empfehlenswerter.

Starten sollte man aber auf jeden Fall mit einer „kleineren“ App, um ein Gespür dafür zu bekommen, wo die Grenzen von ReactNative sind. Je umfangreicher die App, desto mehr Probleme können auftreten. Gerade bei vielen Daten oder beim Thema Sicherheit muss man sich bewusst sein, dass ReactNative  – Stand Frühjahr 2017 – standardmäßig kein komfortables Datenhandling (Datenbank, Zugriff auf der Platte, etc.) und keinen Zugriff auf den iOS-Keychain mitliefert.

Wie starte ich am besten?

Die aktuell wichtigste Seite im Internet zum Thema ReactNative ist https://facebook.github.io/react-native/.

Wer noch keine Erfahrung mit ReactNative gemacht hat, sollte sich zuerst eines der vielen Tutorials im Internet anschauen und sich mit den Components, deren Life-Circle, State-Changes und Imports vertraut machen, bevor man mit dem eigentlichen Projekt beginnt. Es macht auch immer Sinn, kleinere Testprojekte anzulegen, um zum Beispiel ein neues Modul oder eine externe Library zu testen. Verzichten sollte man auch nicht auf ein Versionsverwaltungstool.

Da ReactNative ein relativ junges Framework ist, kann man davon ausgehen, dass noch viel passieren wird. Man sollte sich aber auch bewusst sein, dass hinter dieser Technologie Facebook steht.

_____

Quellen:

https://facebook.github.io/react-native/

http://blog.teamtreehouse.com/introduction-to-react-native

Update LeadHound Visitenkartenscanner auf Version 2.2

LeadHound Visitenkartenscanner erkennt Leads noch schneller

Mit LeadHound geht die Lead-Erfassung schneller. Soweit, so gut. Mit der Version 2.2 wurde die QR-Code-Erkennung in Echtzeit integriert. Noch während Sie die Kamera des iPads ausrichten, erkennt und analysiert die Visitenkartenscanner-Software die Visitenkarte. Befindet sich ein QR-Code aufgedruckt, wird der Nutzer darauf hingewiesen und gefragt, ob der Inhalt des QR-Codes weiterverwendet werden soll.

 QR-Code-Erkennung in Echtzeit mit dem LeadHound Visitenkartenscanner

Editierung wird überflüssig

Wurde der QR-Code verwendet, ist die nachträgliche Leadbearbeitung überflüssig. Die gesparte Zeit können Sie  dazu nutzen, weitere Kontakte zu knüpfen.

IMG_0211

Leads exportieren

Eine weitere Neuerung in Version 2.2 ist der Lead-Export. Zukünftig können Leads im Format *.xlsx exportiert werden. Nicht nur, dass der Export somit einschränkungsfrei mir Excel kompatibel ist, er kann auch per Mail an eine Wunsch-E-Mailadresse gesendet werden. Wem das noch nicht reicht, hat in der neuen Version die Möglichkeit, den Export in einem Cloud-Dienst seiner Wahl zu speichern. Notwendig ist für die Export-Teilen-Funktion nur ein Account bei iCloud, Dropox und Co. Die Cloud-Dienste können übrigens auch seit Version 2.1 beim Fragebogenimport genutzt werden.

IMG_0215

Alle Neuerungen in Version 2.2

– QR-Codes werden live erkannt
– Verbesserung der Lead-Bearbeitung (Löschen per Drag and Drop)
– Automatisches Ausfüllen der Anrede
– Erweiterung der Exportformate (Excel-Support)
– Exports können via Mail sowie an alle gängigen Cloud-Dienste gesendet werden
– Verbesserung der Texterkennung und Zuordnung
– Verbesserungen in der Stabilität und Performance

 

Download und weitere Informationen

Besuchen Sie www.leadhound.de

LeadHound Visitenkartenscanner spart Speicherplatz

Das Update unseres Visitenkartenscanners auf  Version 2.1.1 scheint zwar unscheinbar, hat es aber in sich.

mehr als 50% Speicherplatz sparen

Mit ca. 55 MB Speicherplatz auf der iPad-Festplatte und einer Download-Größe von ungefähr 27 MB wird LeadHound über 50% kleiner als noch in Version 2.1. Zu der Einsparung kam es durch eine Optimierung in unserem OCR-Framework. In Zukunft wir der LeadHound-Download also noch schneller gehen mit gleichzeitiger Speicherplatz-Schonung der Festplatte.

„Eine gute App zeichnet sich durch ihre Kompaktheit und Übersichtlichkeit aus – nicht nur im Design und der Nutzerführung.“
– unbekannter Autor –

Mehr Infos zu LeadHound unter www.leadhound.de.
Direkt zum AppStore geht es über diesen Link: LeadHound herunterladen.

 

größe neu
Auschnitt Tabelle iOS-Geräte mit Download- und Installationsgrößen für LeadHound Version 2.1.1

größe alt

Auschnitt Tabelle iOS-Geräte mit  Download- und Installationsgrößen für LeadHound Version 2.1

Wie funktioniert das Drag’n’Drop-Feature in LeadHound?

Das Drag’n’Drop-Feature in LeadHound soll Nutzern bei der Bearbeitung von Leads helfen. Mit Hilfe von Drag’n’Drop können einzelne Wörter eine Property innerhalb ihrer Property umsortiert werden. Außerdem können Wörter auch in eine andere Property verschoben werden. Die neue Position des Wortes wird dem Nutzer angezeigt.

Wer macht was beim Drag’n’Drop?

Für das Drag’n’Drop- Feature werden Custom-Klassen verwendet, deren Aufgaben im Folgenden beschrieben werden:

Z7DragAndDropTableView:UITableView
Z7DragAndDropRow:UIView
Z7DragAndDropTouchElement:NSObject
Z7DragAndDropTouchView:UIView

dragAndDrop

Z7DragAndDropTableView

//public properties
var wasDragging = false
var dragAndDropRows:[Z7DragAndDropRow] = []
var selectedDragAndDropView:Z7DragAndDropTouchView?
var motherRow:Z7DragAndDropRow?
var touchingRow:Z7DragAndDropRow?

Die TableView ist das DragAndDrop-Hirn. Sie kennt alle DragAndDropRows und weiß, welche TouchView gerade bewegt wird.

Sie weiß außerdem, welches die AusgangsRow ist (motherRow) und über welcher Row sich die TouchView gerade befindet (selectedDragAndDropRow).

Bei ihr kommen alle Touches an, die dann verwaltet werden. Die TableView markiert und bewegt die selektierte TouchView. Außerdem deaktiviert sie bei aktivem Dragging das Scrollen der ScrollView.

Sie aktualisiert regelmäßig alle notwendigen Variablen und verwaltet/bearbeitet auch das Verschieben einer TouchView in einen ungültigen Bereich.

Die Unterscheidung, ob eine TouchView nur angeklickt oder ob sie bewegt wurde, wird in der

touchesMoved(touches: Set, withEvent event: UIEvent?)

geprüft und in der delegate-Funktion der TableView

(-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath)

über

wasDragging

weiterverarbeitet. Hier wird entschieden, ob der Touch an

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

weitergegeben wird.

Implementierung der Z7DragAndDropTableView

Die DragAndDropTableView funktioniert aktuell nur in Verbindung mit einem TableViewController. Die TableView wird per Storyboard mit dem TVC verbunden und ein Outlet wird erstellt.

In der

-(void)viewWillAppear:(BOOL)animated

des TVC wird zuerst reloadData auf dem tableView-Outlet aufgerufen. Anschließend wird die öffentliche Funktion

updateDragAndDropRows()

auf der Z7DragAndDropTableView ausgeführt.

Diese Funktion holt sich aus allen visibleCells alle Zellen, die DragAndDropRows enthalten und speichert diese in der Property

dragAndDropRows

Z7DragAndDropRow

//public properties
var property:BusinessCardProperty?
var textField:UITextField?
var currentPropertyName = ""
var newPositionView:UIView?

Für die DragAndDropRow gibt es zwei Phasen: Init-Phase und Dragging-Phase.

 

Init-Phase

Die DragAndDropRow ist eine Subview der TableView-Zelle.

dragAndDropRow = [[Z7DragAndDropRow alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[cellView addSubview:dragAndDropRow];

Sobald der Zelle Text zugewiesen wird, wird die DragAndDropRow gefüllt. Außerdem werden delegate, das textField und der currentPropertyName gesetzt.

Auf Basis des Texts werden in der DragAndDropRow mit Hilfe der TouchElemente die TouchViews generiert und angeordnet.

Ändert sich der Text wiederholt sich dieser Prozess.

 

Dragging-Phase

Während der Dragging-Phase gibt es drei Fälle, die per HitTest unterschieden werden:
„Abmelden“, „Anmelden“ und „Verschieben innerhalb einer DragAndDropRow“

 

– Fall A: Abmelden

Beim Abmelden wird die TouchView aus dem Array „touchViews“ entfernt und der propertyText angepasst. Unterscheidet sich der propertyText, wird per delegate der Text in CoreData gespeichert.

Die restlichen TouchViews der DragAndDropRow werden neu ausgerichtet.

Anschließend wird über das TouchElement der selektierten TouchView

oldProperty

gesetzt und

currentProperty

entfernt.

 

– Fall B: Anmelden

Hat sich eine TouchView bei einer DragAndDropRow abgemeldet, muss sie sich sofort danach bei einer anderen DragAndDropRow anmelden. Dazu wird zuerst per delegate validiert, ob die neue DragAndDropRow nicht vom Property-Typ „gender“ oder eine „AddNewProperty“-Zelle ist.

Damit die neue TouchView weiß, an welcher Position sie sich in der neuen DragAndDropRow einfügen muss, wird über den x-Wert die nächste TouchView gesucht. Die TouchView wird eingefügt und der Text der neuen DragAndDropRow geändert und gespeichert.

Befinden sich rechts neben der selektierten TouchView noch andere TouchViews, werden diese nach rechts geschoben. Die neue Position wird markiert (newPositionView).

Die Property

currentProperty

des touchElements wird entsprechend gesetzt.

 

– Fall C: Verschieben innerhalb einer DragAndDropRow

Wird eine TouchView nur innerhalb einer Row verschoben, wird per hitTest überprüft wie sich die TouchViews der DragAndDropRow verhalten/ausrichten sollen.

Die neue Position wird mit der newPositionView angezeigt. Ändern sich die Positionen, wird das Array der TouchViews angepasst und der Text aktualisiert, was immer wieder eine Speicherung der Property in CoreData mit sich bringt.

Nachdem die selektierte TouchView losgelassen wird, geht sie an ihre entsprechende Stelle in der DragAndDropRow.

Z7DragAndDropTouchElement

// public properties
var text:String?
var currentProperty:String?
var oldProperty:String?

Ein TouchElement wird beim Anlegen der DragAndDropRow generiert und mit einem Wort und dem currentPropertyName der DragAndDropRow initialisiert.

Das TouchElement ist immer als Property einer TouchView gesetzt. Ändert sich die DragAndDropRow der TouchView, werden die currentProperty und die oldProperty aktualisiert.

Z7DragAndDropTouchView

// public properties
var title:String?
var touchElement:Z7DragAndDropTouchElement?
var label:UILabel?

Die TouchView wird per DragAndDrop verschoben. Initialisiert wird sie durch das TouchElement.

init(text:String?, currentProperty:String?) {
    super.init()
    self.text = text
    self.currentProperty = currentProperty
}

Beim Wechsel in eine andere Row ändern sich die Properties des TouchElements.

 

Automatische Inkrementierung der Bundle Version in Xcode 4

Apple fordert in seinen Guidelines für die Entwicklung von Apps für IPhone, iPad wie auch Mac OSX eine stete Inkrementierung der Versionsnummer wenn eine App im AppStore aktualisiert werden soll. Aber auch für die Entwicklung kann eine fortlaufende Nummer hilfreich sein. Gerade wenn man die App an Beta Tester via adHoc Distribution herausgibt. So lässt sich immer nachvollziehen, welche Entwicklungsversion beim Tester installiert ist und der Fehler kann besser gefunden werden.

Jedoch ist es lästig immer erst die Versionsnummer zu verändern wenn ein neuer Build geschrieben wird. Daher im folgenden nun eine Automatisierung des Ganzen mit Hilfe von Xcode. Wichtig ist es übrigens nicht nur die „Bundle version“ in der project-info.plist anzugeben, sondern auch den Wert für „Bundle versions string, short“.

Für die Automatisierung wird eine xcconfig-Datei benötigt. Dazu einen Rechtsklick auf das Projekt ausführen und „New File…“ auswählen. Im nun angezeigten Popup unter „Other“ den Typ „Configurations Settings File“ auswählen. Nach dem Klick auf Next wird nach dem Dateinamen gefragt. Für diese Beispiel hier verwende ich „version“. Nachdem die Datei erzeugt ist, darauf achten dass sie auf der obersten Ebene im Projekt, als im Projectroot, liegt.

Anschließend folgt die Anpassung der Datei. Wenn man sie öffnet ist die noch leer, bis auf den vorkonfigurierten Kommentarheader. Hier fügt man nun folgende Zeile ein und speichert das ganze:
CURRENT_PROJECT_VERSION = 1

Weiter geht es mit den Einstellungen im Projekt. Dazu links das Projekt auswählen und der nun angezeigten View ebenfalls links unter „Projects“ das entsprechende Projekt auswählen. Im Tab „Info“ gibt es nun die „Configurations“ für das Projekt. Standardmäßig sind das „debug“ und „release“. Nun eine Konfiguration auswählen, aufklappen und für den Wert „Based on Configuration File“ die eben erstellte Datei auswählen für Project und Target. Standardmäßig steht hier „None“. Diesen Schritt für alle Konfigurationen wiederholen, für die man die automatische Inkrementierung haben möchte.

Nun müssen noch die Einstellungen für die Targets angepasst werden. Dazu eben das Projekttarget in der linken Spalte der Hauptview auswählen, welches direkt unter den Projects steht. Nun wird in der angezeigten View unter „Info“ die project-info.plist angezeigt in der sich auch die Einträge „Bundle version“ und „Bundle versions string, shot“ finden sollten. Diese Werte jeweils auswählen und mit folgenden String ersetzen:
1.0.${CURRENT_PROJECT_VERSION}
In diesem Beispiel bedeutet dies, dass die Hauptversion bei 1 liegt und die Unterversion bei 0. Aber der letzte Wert wird nun aus der Datei gezogen und stellt somit die build-Version dar.

Als letzter Schritt muss nun Xcode gesagt werden, dass es diesen Wert hochzählen soll wenn ein neuer build ansteht. Dazu bleibt man in der Target-Ansicht und wählt hier den Tab „Build Phases“ aus (2. Tab rechts neben Info). In der angezeigten View gibt es unten rechts den Button „Add Build Phase“. Diesen anklicken und im angezeigten DropDown „Add Run Script“ auswählen. Nun sollte oben der Bereich „Run Script“ erscheinen, insofern er noch nicht vorhanden war. Diesen aufklappen, wenn dem noch nicht so ist und nun folgende Anpassungen ausführen. Der Wert bei Shell sollte „/bin/sh“ sein und im folgenden Textfeld folgendes Script einfügen:
NEW_VERSION=`cat "$SRCROOT/version.xcconfig" | awk '/CURRENT_PROJECT_VERSION/ { print $3 + 1 }'`
sed -i '' "s/CURRENT_PROJECT_VERSION = .*/CURRENT_PROJECT_VERSION = $NEW_VERSION/" "$SRCROOT/version.xcconfig"
CURRENT_PROJECT_VERSION=$NEW_VERSION
touch "$SRCROOT/version.xcconfig"

Dieses Script zieht sich die aktuelle Versionsnummer aus der Datei und aktualisiert diese.

Das waren alle Anpassungen die nötig sind. Zum Testen des Ganzen, nun einfach einen Build des Projektes herausschreiben. Schaut man nun in die version.xcconfig Datei, ist der darin stehende Wert um 1 erhöht. Auch die Versionsnummer der App ist inkrementiert worden. Dazu links im Project-Browser unter Products > Im Finder anzeigen auswählen. Die angezeigte Datei hat nun ebenfalls die aktualisierte Versionsnummer.