NSOutlineView zeigt nur „Table View Cell“ an

Gestern versuchte ich ein NSOutlineView mit einer Datenstruktur zu befüllen. Nachdem dies gelungen war, gab es allerdings ein Problem. Das NSOutlineView zeigte für jeden Eintrag immer nur Table View Cell als Beschriftung an.

Der Objektinspektor unter Xcode

Der Objektinspektor unter Xcode

Die Lösung für das Problem ist dabei relativ simpel, wenn man weiß an welcher Stelle man suchen muss. So muss der Content Mode des NSOutlineView von View based auf Cell based umgestellt werden. Anschließend werden die Einträge, welche durch die von NSOutlineViewDataSource abgeleitet Klasse bereitgestellt werden, korrekt dargestellt.

Pattern für asynchronen Timer

In den letzten Tagen habe ich nach einem Pattern für C#/.NET gesucht welches elegant einen Timer zur Verfügung stellt. Gestoßen bin ich dabei auf ein Pattern, welches sich die neuen Keywörter async und await aus den aktuellen C#-Versionen zu Nutze macht. Mit Hilfe dieser Schlüsselwörter lassen sich nebenläufige Funktionen ohne größeren Overhead entwickeln. Die Timer-Funktion sieht dabei so aus:

async void StartPollingTimer()
{
    while(true)
    {
        await Task.Delay(2000);

        //Do something
    }
}

Aufgerufen wird das ganze dabei einfach mittels:

StartPollingTimer();

Der Entwickler muss sich dabei nicht mehr um die Thread-/Task-Verwaltung kümmern und kann damit auf die Schnelle einen Timer implementieren, welcher asynchron läuft.

NSSpeechSynthesizer und NSSpeechRecognizer unter Mono nutzen

Unter Mac OS X gibt es in der API die Klassen NSSpeechSynthesizer und NSSpeechRecognizer. Während die eine Klasse dazu dient Text auszugeben, kann die andere Klasse dazu genutzt werden Sprache zu erkennen. Der NSSpeechSynthesizer kann unter Mono einfach genutzt werden:

var synthesizer=new NSSpeechSynthesizer();
synthesizer.StartSpeakingString("Hallo Welt.");

Schwieriger wird das ganze bei der Klasse NSSpeechRecognizer. Mit Hilfe dieser Klasse ist es möglich auf bestimmte Kommandos zu reagieren. Im ersten Moment muss die Klasse angelegt werden und einige Optionen gesetzt werden:

var recognizer=new NSSpeechRecognizer();

string[] cmds=new string[] {"Computer"};

recognizer.Commands=cmds;
recognizer.BlocksOtherRecognizers=false;
recognizer.DisplayedCommandsTitle="RecognizerTest";
recognizer.Delegate=new RecognizerDelegate();

recognizer.ListensInForegroundOnly=false;
recognizer.StartListening();

Wenn nun das Kommando Computer erkannt wird, wird die Instanz vom RecognizerDelegate angerufen. Das Delegate sieht dabei wie folgt aus:

public class RecognizerDelegate : NSSpeechRecognizerDelegate
{
    public override void DidRecognizeCommand(NSSpeechRecognizer sender, string command)
    {
        //Do something
    }
}

Im Delegate selbst gibt es die Methode DidRecognizeCommand welche als Parameter das erkannte Kommando enthält.

Eine Statusbar-App für Mac OS X mittels Mono und Xamarin Studio entwickeln

Bei Mac OS X befindet sich oben am Bildschirmrand die Menü- und Statusbar. In diesem Artikel soll es darum gehen, eine solche Statusbar-App in Mono mittels des Xamarin Studios zu erstellen. Im ersten Schritt wird dazu ein neues MonoMac-Projekt im Xamarin-Studio angelegt. Wenn man dieses Projekt startet, findet man ein leeres Mac OS X-Fenster vor.

Ein neues MonoMac Projekt wird angelegt

Ein neues MonoMac Projekt wird angelegt

In dem neu angelegten Projekt wird eine neue Klasse mit dem Namen AppController angelegt. Diese wird mit folgendem Inhalt gefüllt:

using System;
using MonoMac.Foundation;
using MonoMac.AppKit;

namespace StatusBarApp
{
    [Register("AppController")]
    public partial class AppController : NSObject
    {
        public AppController()
        {
        }

        public override void AwakeFromNib()
        {
            var statusItem = NSStatusBar.SystemStatusBar.CreateStatusItem(30);
            statusItem.Menu = statusMenu;
            statusItem.Image = NSImage.ImageNamed("status");
            statusItem.HighlightMode = true;

            mcQuit.Activated+=(object sender, EventArgs e) =>
            {
                NSApplication.SharedApplication.Terminate(this);
            };
        }
    }
}

Damit die Anwendung kein Menü und kein Dock-Icon mehr besitzt, müssen wir die Info.plist bearbeiten. In dieser Datei muss ein neuer Schlüssel mit dem Namen Application is agent (UIElement) und dem Typ Boolean angelegt werden. Der Wert des neuen Schlüssels wird dabei auf YES gesetzt.

Der neue Schlüssel wird mit dem PList-Editor des Xamarin Studios hinzugefügt

Der neue Schlüssel wird mit dem PList-Editor des Xamarin Studios hinzugefügt

Nun öffnen wir die Datei MainMenu.xib, welche von Xamarin Studio in Xcode geöffnet wird. Hier ziehen wir ein neues Objekt vom Typ Menu in den Designer und entfernen alle Einträge bis auf einen. Dem verbliebenen Eintrag geben wir die Beschriftung Quit. Anschließend fügen wir ein Object hinzu und begeben uns in den Identity Inspector. Dort tragen wir bei Custom Class unter Class den Namen AppController ein. Das vorhandene Hauptmenü kann anschließend entfernt werden.

Das Design unter Xcode

Das Design unter Xcode

Nun muss das Menü mit dem Quellcode verbunden werden, dazu wird der Assistance Editor in Xcode geöffnet. Als Quelltext wird auf der rechten Seite des Editors die Datei AppController.h ausgewählt. Nun wird das Menü mittels gedrückter Steuerungstaste (Strg/Ctrl) in die Headerdatei gezogen. Damit legen wir ein Outlet an. Dieses bekommt den Namen statusMenu. Das gleiche wird anschließend mit dem Menüeintrag Quit gemacht. In diesem Fall wird dabei eine Action definiert, welche den Namen mcQuit bekommt. Nun kann Xcode wieder geschlossen werden.

Dem Projekt muss nun noch eine 29×22 Pixel große Grafik hinzugefügt werden. Die Grafik (in diesem Fall status.png) wird beim Laden als Icon für die Statusleiste genutzt. Als letzten Schritt können die Dateien MainWindow.cs, MainWindow.xib und MainWindowController.cs entfernt werden. Nachdem diese Objekte auch im AppDelegate entfernt wurden, ist die Anwendung fertig. Der Quelltext des Projektes kann sich auch heruntergeladen werden. Er kann dabei von jedermann frei verwendet (Public Domain) werden.

Geforktes Git-Repository vom Original aktualisieren

Auf Plattformen wie GitHub ist es ganz einfach bestehende Projekte zu forken, sie bei sich weiterzuentwickeln und die Änderungen an das Original-Projekt zurückzugeben. Ein klein wenig komplizierter ist es das geforkte Git-Repository wieder vom Original aus zu aktualisieren. Im ersten Schritt muss dabei im geforkten Repository ein Upstream definiert werden. Dies geschieht im Terminal mit dem Befehl (in diesem Falle auf GitHub bezogen):

git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git

Mittels des Befehls git remote -v kann anschließend überprüft werden ob der Eintrag vorgenommen wurde. Nun können die Änderungen vom Remote upstream in das lokale Git-Repository mittels:

git pull upstream master

übernommen werden. Anschließend kann man das ganze noch mittels git push auf den entfernten Server übertragen.