Wachgeblieben!

Energiesparen ist IN. Und natürlich bietet OS X wie jedes andere moderne Betriebssystem auch reichlich Features um den Energie-Hunger von Desktop oder Laptop effektiv in den Griff zu kriegen. Es gibt allerdings einige Situationen, in denen es unerwünscht ist, wenn OS X sich mir nichts dir nichts schlafen legt, so zum Beispiel bei längeren Downloads oder aufwendigen Rechenprozessen.

Der sogenannte Standby-Modus lässt sich über die Systemeinstellungen selbstverständlich unterbinden, oft vergisst man jedoch diese Ausnahme-Einstellungen wieder zurückzudrehen.

Die bessere Lösung für mich ist ein Minitool namens Caffeine, das auf Wunsch automatisch beim Hochfahren von OS X startet und sich unauffällig als Kaffee-Tasse in die Menüleiste einnistet:

caffeine_osx_01

Ist die Tasse leer verhält sich der Mac wie gewohnt, füllt man sie hingegen durch einen schnellen Klick mit Kaffee auf schläft OS X von da ab nicht mehr ein. Ebenso schnell ist der Allzeit-Wach-Modus durch einen weiteren Klick wieder beendet.

Caffeine findet sich kostenlos im Mac App-Store oder auf den Seiten des Herstellers Lighthead.

XCode, iOS-Retina-Resourcen und das Problem mit Subversion

XCode tut sich manchmal etwas schwer mit Subversion. Man merkt eindeutig, dass GIT die von Apple favorisierte Versionsverwaltungs-Lösung ist. Viele Programmierer nutzen darum Subversion einfach über das Terminal statt aus XCode heraus. Probleme macht iOS-Programmieren oft dabei das Hinzufügen von Retina-Resourcen zu Subversion.

Ein Beispiel: Wir haben ein Bild namens MeinBild.png und die zugehörige Retina-Variante MeinBild@2x.png . Das Kommando zum Hinzufügen der Retina-Version wäre

svn add MeinBild@2x.png

Subversion wird jedoch durch das @ gestört. Für SVN signalisiert das letzte @ einer Zeile die Angabe einer Revision.

Die Lösung für dieses Problem ist bei Subversion-Kommandos einfach ein weiteres @ ans Ende des Dateinamens anzuhängen:

svn add MeinBild@2x.jpg@

Die genannte Lösung ist detaillierter als hier auf StackOverflow diskutiert worden.

Falls SQLServer ReportingServices (SSRS) mal Leerzeichen verschluckt

Heute ist uns im Projekt aufgefallen, dass SSRS-Tabellenfelder und Textboxen gerne mal Leerzeichen verschlucken. Ärgerlich ist das bei fest formatierten Textbausteinen, wie sie bei Labeltexten häufiger auftreten. Das Problem liegt daran, dass Tabelleninhalte im Report als HTML gerendert werden. Darunter leiden Zeilenumbrüche zwar nicht, aber Spaces am Zeilenanfang oder Folgen von mehreren Spaces werden dabei einfach verschluckt.

Die Lösung ist es wie bei HTML üblich Non-Breaking-Spaces in den Report zu streuen. Diese kann man mit Tastencode ALT-0160 in Windows erzeugen.

Natürlich sind diese wieder alles andere als schön in der Datenbank mit den Labeltexten und unpraktisch beim Einpflegen der Texte.

Besser ist es also die Spaces im Report zu wandeln. Dies kann in der Expression der entsprechenden Control passieren mittels

=REPLACE(Feld.Value," ", " ")

Das zweite Space in der Expression wird dabei natürlich als ALT-0160 via Ziffernblock eingegeben.

MS SQL Server Datetime mal ganz zeitlos

Nach mehreren anderen Varianten habe ich heute endlich die vermutlich performanteste Routine zum Entfernen des Uhrzeit-Anteils aus einem MS SQL Server Datetime Ausdruck gefunden:

    select DATEADD(dd,0,datediff(dd,0,GETDATE()))

Der Trick dabei ist, dass SQL Server die Zahl 0 als ein fixes Bezugsdatum interpretiert. Das Beispielstatement

    select DATEADD(dd,0,0)

zeigt uns das interne Tag Null Referenzdatum 1. Januar 1900.

Die Datediff-Differenz zwischen diesem und dem aktuellen Datum sagt uns wieviele Tage seit dem 1. Januar 1990 vergangen sind. Addiert auf das Bezugsdatum 0 ergibt sich somit wieder das heutige Datum — nur halt ohne Zeit.

Da nur Integer-Operationen genutzt werden statt komplexerer Umwandlungen ist diese Routine viel schneller als String-Format-Umwandlungen wie beispielsweise

    select convert(datetime,convert(varchar(8),GETDATE(),112))

Es bietet sich an unsere Rechenroutine als Funktion anzulegen:

    CREATE function [dbo].[getDateWithoutTime] (@mydate datetime)
    returns datetime
    as
    begin
        return DATEADD(dd,0,datediff(dd,0,@mydate))
    end

Image Cache Probleme von XCode 4 in den Griff kriegen

Gestern hatte ich schon darüber berichtet, dass XCode 4 und sein integrierter Interface-Builder manchmal Probleme mit dem Anzeigen von Images in der IDE haben. Das Problem war temporär durch Verschieben oder Umbenennen des Projektverzeichnisses zu lösen, so daß ich fehlerhafte Cache-Strukturen vermutet.

Heute habe ich herausgekriegt wie das Problem entsteht und wie man es lösen kann. Zunächst einmal liegt es weder an korrupten Projektdateien noch an einem ausstehenden CLEAN auf das Projekt oder Target. Das ist sicher schon mal beruhigend: Es ist nichts kaputtgegangen.

Den wahren Übeltäter habe ich gefunden als ich in die Xcode Preferences geschaut und dort das Locations-Menü inspiziert habe. Hier gibt es Einträge für „derived data“, also „abgeleitete Daten“ wie Builds, Logs und Indexes.

xcode4imagecache01

Und diese „Derived-Data“-Ordnerstrukur ist die Problemquelle. Hier werden Resourcen, die im XCode-Quellverzeichnis liegen, für die IDE in gewandelter Form temporär gecached. Der Interface-Builder zieht in der IDE seine Images aus diesem Ordner, nicht direkt aus dem Quellverzeichnis.

Manchmal wenn man nun Bilddateien verschiebt oder neu in XCode in Gruppen anordnet verliert XCode den Zusammenhang zwischen Cache und Quelle. Genau das ist der Zeitpunkt ab dem Bilder im Interface-Builder nicht mehr angezeigt werden.

Ein CLEAN löst das Problem nicht da es nur die Compiler-Caches leert.

Ein Kopieren des Projekts in einen neuen Ordner legt auch einen neuen Derived-Data-Ordner an. Jedoch bleibt auch der alte Derived-Data-Ordner bestehen, so daß beim Zurückkopieren in den alten Originalordner das Problem wieder auftaucht.

Mit dem Organizer kann man die Derived-Data-Ordner einer Anwendung anzeigen:

xcode4imagecache02

Und exakt hier kann man diese Caches auch gefahrlos löschen. Danach sind alle Probleme mit dem Interfacebuilder beseitigt und die Bilder werden wieder korrekt angezeigt. Alternativ können die zugehörigen Ordner auch mittels Finder oder Terminal aus den angegebenen Pfaden gelöscht werden.

Falls InterfaceBuilder mal Images verschluckt

Sollte XCode mal Eure Images nicht mehr anzeigen in NIBs (obwohl sie im laufenden Programm oder im Simulator normal zu sehen sind):

  • Einfach Xcode schliessen,
  • den Projekt-Ordner auf den Desktop kopieren,
  • das Projekt aus dem kopierten Ordner öffnen.

Mysteriöserweise funktionieren die NIBs dann auch im Interfacebuilder wieder.

Das ganze scheint mir ein internes Caching-Problem des Interfacebuilders zu sein, und das egal ob in Version 3 oder 4. Ich denke das Problem tritt verstärkt dann auf wenn man das Projekt auf mehreren Rechnern in verschiedenen Ordnern bearbeitet und zwischen den beiden Maschinen ab und an hin- und herkopiert.

Das große UITextView-Rätsel

Eben durfte ich bei meiner Cocoa-Einarbeitung das große UITextView-Rätsel lösen.

Die Fragestellung dabei: Wie setzt man den Font einer UITextView-Control via InterfaceBuilder? 

Hintergrund des Problems: Jedes andere Control-Element zeigt ein Fontfeld im Inspector. Der UITextView nicht. Klar ginge es programmatisch, aber das wäre ja geschummelt. Es sollte schon beim interaktivem Editieren des Nibs möglich sein.

Die Lösung ist so einfach, dass man kaum darauf kommen kann: Man betätigt einfach CMD-T sobald das TextView-Element selektiert ist. So wie fast überall in OSX.

Warum aber ausgerechnet diese Control das Font-Attribut nicht auch im Inspector anbietet bleibt weiterhin ein Rätsel.

UDID eines iPhones via iTunes ermitteln

OS und der AppStore sind wie wir alle wissen ein geschlossener Garten. Eine Folge davon: Will man die Beta-Version einer Software an Tester oder Kunden ausliefern muss man für das Provisioning die Zielgeräte kennen. Für diesen Zweck hat jedes iPhone eine eindeutige UDID. Diese lässt sich sehr leicht via XCode und Organizer ermitteln, aber der Kunde oder Betatester hat nicht immer die komplette Entwicklungsumgebung installiert und im Zugriff. Glücklicherweise kann man die UDID aber auch über iTunes ermitteln.

Klicken wir in iTunes auf den Sidebar-Eintrag eines angeschlossenen iOS-Gerätes, zeigt es uns zunächst bereitwillig seine Seriennummer, nicht jedoch die für die Registrierung wichtige UDID:

udid01

Diese kann man aber an selber Stelle ermitteln indem man die angezeigte Seriennummer anklickt:

udid02

Auch die anderen Dialog-Felder zeigen auf Klick weitere Informationen, beispielsweise IMEI und Buildversion.

Von Word-Vorlage nach SSRS-Report

Derzeit erstelle ich für einen Kunden mehrere neue Reports mittels SQLServer Reporting Services (SSRS). Die Vorgaben dafür sind mehrere Beispiel-Word-Dokumente, die möglichst genau umzusetzen sind. Ein Szenario, das vermutlich ziemlich häufig auftritt, das sich was Zeilenabstände angeht aber garnicht mal so leicht gestaltet: Das Demodokument beinhaltet mehrere Textboxen, in jeder sind die Fontgrößen leicht anders eingestellt, und Word kümmerte sich ja selbstständig um die Abstände beim Umbruch. Wie simuliert man so etwas aber in SSRS ohne viel Rechnen und Herumschieben von Textboxen? Ich habe mir dabei wie im folgenden beschrieben geholfen.

Zeichensätze in Word haben Punkt-Angaben. Punkte (pt) sind 1/72 inch groß. Ein Inch widerum hat 2,54 cm. Für eine Textbox, die einen 8pt Font aufnimmt, setze ich eine Höhe von 8 + 1 pt. Das kommt sehr nah an die von Word gewählten Abstände.

Was ist das nun in cm? Einfacher Dreisatz: 2,54cm / 72 x 9 = 0,3175 cm. Prima. Allerdings sind 0,3175 cm nicht so leicht zu positionieren, da hilft auch ein Gitter nicht sonderlich viel. Die folgende Lösung scheint mir am effizientesten für SSRS zu sein:

Als Höhe ist der Wert schnell auf mehreren Boxen eingestellt: Eine der Textboxen wird auf die Höhe angepasst, die weiteren hinzu-selektiert, und den Rest macht der Toolbar-Button „Höhe angleichen“.

Um nun die Boxen mit richtigen Zeilenabständen vertikal zu positionieren hilft ein weiterer Button namens „vertikalen Abstand entfernen“. Ich finde das spart nun wirklich unglaublich viel Zeit und Rechnerei. Man muss ihn nur erstmal entdeckt haben.

Ein weiterer Faktor ist aber noch im Weg: Das Default-Padding einer Textbox ist 2pt;2pt;2pt;2pt. Dieses müssen wir für unsere Boxen auf 0pt;0pt;0pt;0pt ändern, ansonsten würde an allen Seiten zusätzlicher freier Raum um unseren Text gelassen. Das möchten wir in diesem Fall natürlich nicht.

Ein abschließendes Tuning, das verhindert, dass es uns das Layout bei langen Texten mal um die Ohren haut: Wir schalten die CanGrow-Option der Textboxen aus.

Ich denke die obigen Sachen nehmen dem Wandeln von Word nach SSRS-Report erstmal die größten Schrecken.

jqGrid hat echt was

In den letzten Wochen konnte ich mich etwas ausgiebiger mit jqGrid beschäftigen, und ich muss sagen: Diese AJAX-Tabellen-Komponente hat was. Es gibt kaum etwas, was ich als Feature in anderen Tabellenkomponenten kennengelernt habe, das hier fehlen würde. Die zugehörige Demoseite beweist das denke ich eindrucksvoll. Allerdings ist der Einstieg nicht ganz leicht, der Technologiebaum dahinter ist schon recht tief.

jqGrid baut auf JQuery UI auf, das dann widerum auf JQuery. Letzteres setzt obwohl es JavaScript stark vereinfacht doch hier und da detailliertere JavaScript-Kenntnisse voraus (der ideale Einstieg hierfür ist immer noch der O’Reilly JavaScript Definitive Guide und online die JavaScript-W3School).

Für das Backend, das für die Komponente Daten heranschafft, kommt nochmal die eine oder andere Technologie hinzu. Hier ist die Wahl aber frei, solange das Framework jqGrid mit JSON oder XML-Daten befeuern kann. Das Format kann relativ weiträumig angepasst werden: jqGrid offeriert Default-XML/JSON-Formate, erlaubt aber die Konfiguration seines XML-Readers, falls man das Quellformat nicht anpassen kann. Einschränkung dabei: jqGrid kann derzeit nur XML-Tags, nicht aber XML-Attribute als Datenquelle heranziehen.

Hat man ein erstes jqGrid-Skript vor sich, ist oft nicht ganz klar, welches Feature aus welchem Paket kommt. Ich bin wirklich froh Firebug als Firefox-Extension mit an Bord zu haben, sonst würde ich wohl heute noch nicht verstehen wie das Ganze zusammengreift.

Was wirklich hilft bei der optischen Gestaltung des Grids ist, dass diese mittels JQuery UI Themerollererfolgen kann. Im Projekt hat unsere Designerin hiermit relativ schnell ein passendes Theme erstellen können, das mit meiner Grid-Software-Demo auch sofort reibungslos zusammengespielt hat.

Fallstricke bei jqGrid: Das eine oder andere JQuery Plugin muss hinzugefügt werden, damit alle Features funktionieren. Will man beispielsweise mit einem komfortablen Editor Tabellenspalten des Grids sortieren oder filtern, wird die Multiselect Komponente nötig. Achtung dabei: Von dieser gibt es mehrere Quellcode-Varianten im Internet, die nicht alle mit jqGrid zusammenspielen. Der richtige Ort für die Komponente ist Github, das ich so als Social Coding Dienst auch mal kennenlernen durfte.

Fazit: jqGrid ist eine sehr starke Client-Tabellenkomponente für Webanwendungen, man darf die Einarbeitungszeit allerdings nicht unterschätzen. Grob 2-3 Tage sind nötig bis man damit produktiv ist. Danach hat man aber auch JQuery und JQuery UI deutlich besser im Griff. Die Dokumentation ist noch etwas schwach, wäre diese besser, wäre auch sicher der Einstieg reibungsloser. Auch sollte man beachten, dass Javascript recht viel Last auf den Clientbrowser legt. Manchmal ist es sicher sinnvoller seine Tabellen im Backend aufzubauen und via reinem HTML in den Browser zu bringen. Für ein solches Szenario hat sich bei mir Displaytag sehr bewährt.