+49 40 608 12 460 (Development)
+49 175 5611694 (Kommunikation)

Hyperloop als Modul in Ti.Current

Als Alternative zur direkten Kompilierung in der Shell, kann (zumindest für iOS) Hyperloop auch als Modul kompiliert werden.

Dazu muss vorerst Hyperloop auf der Maschine installiert werden:

 npm install -g git://github.com/appcelerator/hyperloop.git

Falls npm noch nicht auf der Maschine gefunden wird, kann es von nodeJS geholt und installiert werden.

 

Das Titanium Studio kann von Appcelerator runtergeladen und installiert werden. Es benötigt einen kostenlosen Account. Jetzt können wir über /File/New/MobileApp Project ein neues Modul anlegen:

Der Wizard legt jetzt ein Modulverzeichnis an. Darin muss händisch ein Verzeichnis js angelegt werden. Das ist das Verzeichnis, in dem die hjs-Dateien liegen. Im einfachsten Fall gibt es nur eine Datei mit dem Namen app.hjs.

@import("Foundation");
@import("UIKit");

String.prototype.toUTF8 = function() {
	return NSString.stringWithUTF8String('' + this);
};

module.dispatch_async(function(){
	var win = UIApplication.sharedApplication().keyWindow,
	var label = new UILabel();
	label.textColor = UIColor.darkTextColor();
	label.frame = CGRectMake(20, 20, 280, 230);
	label.font = UIFont.systemFontOfSize(24);
	label.textAlignment = NSTextAlignmentCenter;
	label.lineBreakMode = NSLineBreakByWordWrapping;
	label.numberOfLines = 0;
	label.text = 'Hello world'.toUTF8();
	win.addSubview(label);
});

exports.foo = function(){
	return 'bar';
};

Das war es schon. Nun können wir unser Modul mit Hyperloop kompilieren. In nachfolgender Zeile muss selbstverständlich der Pfad zum Projekt angepasst werden:

hyperloop package module --platform=ios --src=~/PFAD/simplehlmodule --dest=build

Fas Echo auf der Konsole sieht etwa so aus – wobei das sehr lange dauern kann:

[INFO]  Generating system metabase will take up to a minute (or greater) depending on your environment. This file will be cached and will execute faster on subsequent builds.
  ◟ Generating system metabase

[INFO]  Compiling 816 source files
[INFO]  Generated universal library file at build/libSimpleHylooModule.a
[INFO]  Compiling 6 source files
[INFO]  Creating module zip distribution
[INFO]  Created module distribution: build/de.appwerft.simplehlmodule-iphone-1.0.zip

Hyperloop legt jetzt im Projektverzeichnis des Moduls unter anderem ein build-Verzeichnis an. Dort liegt als Ergebnis eine ZIP-Datei, die dann wie üblich zu installieren ist. Im einfachsten Fall wird das Paket ausgezippt und das module-Verzeichnis in das Projektverzeichnis der App, die das Modul aufrufen soll kopiert. Das module-Verzeichnis liegt dann parallel zum Resourcen-Verzeichnis.

Nun bilden wir beispielhaft ein Miniprojekt und binden unser Modul ein.

Das Hyperloopmodul muss nicht nur im Dateisystem liegen, es muss auch ins Projekt importiert werden. Das geschieht in der tiapp.xml mit dem Eintrag:

<modules>
   <module platform="iphone">de.appwerft.simplehlmodule</module>
</modules>

In dem Projekt löschen wir in der app.js im Verzeichnis Resources den Dummyinhalt und kopieren diese Zeilen hinein:

var win = Ti.UI.createWindow({
             backgroundColor:"white"
          });
win.open();
var module = require("de.appwerft.simplehlmodule");
alert(module.foo());

Nun kann wie gewohnt das Miniprojekt kompiliert und der Simulator gestartet werden.

Gegenwärtige Begrenzungen und Probleme

  1. Falls im Modul native Methoden aufgerufen werden sollen, muss wie im Beispiel die Methode module.dispatch_async() aufgerufen werden. Dies ist wegen der unterschiedlichen Thread-Architektur notwendig. Mehr in den untigen Nachbemerkungen zur Threadbehandlung.
  2. Derzeit wird nur ein Modul pro App unterstützt.
  3. Hyperloop-Module nutzen die neue commonJS-Logik.  Wenn also in hjs-Dateien require verwendet wird, muss die neue Logik verwendet werden. Modulaufrufe in JS-Dateien folgen dem alten Schema. An dem Angleich arbeitet zur Zeit Jeff Haynie.

Thread-Architektur

Da Ti.Next und Ti.Current mit verschiedenen Thread-Architekturen arbeit, muss eine Brücke genutzt werden. Dazu gibt es die Methode module.dispatch_async(). Sie erlaubt den Zugriff  auf den Main-UI-Thread. 

 

Bei Verwendung der Titanium API braucht man diese Brücke nicht, weil diese APIs schon im richtigen Thread werkeln. Andererseits braucht man sie, wenn native APIs direkt aufgerufen werden sollen.

Im nächsten Kapitel geht es um die Einbindung von npm zur Moduleverwaltung in Hyperloop.