Xcode で GUI アプリ

これまで、主にコマンドラインツールを作成してきた。

ある程度、Objective-C の様子もわかったきたと思うので、GUI アプリの作成に手をつけてみよう。

プロジェクトの作成〜実行

Xcode を起動して新しいプロジェクトをつくる。

Command Line Tool ではなく、App の方を選ぶ。

次に Product Name などを決めるダイアログが出現する。

ワイは cocoa-sample としたが、名前などは適当に。

言語は Objective-C で。

悩みどころは、interface の選択で、いくつか候補はある。

アップルのアプリの GUI に関しては、歴史的には、 Nib → Xib → Storyboard → SwiftUI の順番で発展してきた。
(ただし、現状では開発言語を Objective-C を選択した場合は SwiftUI は選べない。なお、Nib は Next Interface Builder から。Xib の X は XML から)

iOS の影響なのか Storyboard で説明してあるサイト・教科書がほとんどだが、今でもレガシーなプロジェクトでは Xib は使われている。さすがに Nib は見かけないが。

GUI のシステムは度々変更されるので、表面的な操作だけではなく、その意味を把握することを意識しておくと少々の変更があっても対応することができると思う。

プロジェクトを作成するといくつかのファイルが自動生成される。

いきなりだが、この時点で run させてみよう。

ここまでの手順が間違ってなければ、以下のようなウィンドウが出現する。

ここまで1行のコードも書かずに Mac ネイティブなウィンドウをディスプレイ上に表示できているわけだから、世間的にはこちらの流儀がメインとなっていくのはわからないでもない。

しかし、である。

知識や理解などがこのレベルに留まっている人は多いようだ。

このレベルだと狙った機能を独自に実装する、というような作業は無理ではなかろうか。

自動生成されたファイルなどの意味をもう少々深掘りしよう。

main.m の意味

main.m の具体的なコードは以下のようになっている。

#import <Cocoa/Cocoa.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
    }
    return NSApplicationMain(argc, argv);
}

GUI メインで学んできた初学者に「argv って何?」と聞いてもうまく答えられる人はそう多くない。

ワイがまず最初にコマンドラインツールやらポインタの説明をしたのは、ここら辺の理解を深めるためってのもある。

要するにこのコードは argc と文字列配列(のポインタ)argv を NSApplicationMain() に与え、そこからの返り値を待っているという機能をになっている。

では、NSApplicationMain が何かといえば、アプリケーションを管理しているクラスを呼び出す関数ということになる。

ここら辺は日本語記事もあるし、アップル公式の説明でもなんとかなると思う。

ところで、初学者にどの程度まで説明するのか?というのは難しい問題も孕んでいる。

NSApplicationMain にしても、「NS は NextStep に由来する」のようなマメな知識をさしはさんでいるサイトはあるが、「Objective-C/C++ では名前空間の概念がないため、クラスやそのメンバー関数を命名する際には慣例的に大文字2文字を先頭につける」といったところまで説明しているサイトはほぼない

AppDelegate と ViewController

だんだん理解があやしくなってくるのが、AppDelegate や ViewController だろう。

ただ、ちょっと先を急ぎたいので、ここはワイも流させてもらう。

あるアプリが main.m を経て NSApplicationMain で示される何かで管理されているとき、全てが管理されていたのでは、独自実装はできなくなってしまうので、動作の要所要所で独自処理を指示できる箇所が AppDelegate だ、という説明ではどうだろう?

WindowController

cocoa アプリのプロジェクトを作成したとき、AppDelegate と ViewController に対応するファイルは自動で生成される。

が、実際にウィンドウシステムを動作させるとき、これを管理するクラスも必要だ。
結論から先に書くと、これが WindowController クラスで、Xcode 上でも確認できる。

Main.storyboard を選んだ際、これを構成する Scene が表示されるが、Window Controller はしっかりありますよね?

ファイルでは生成されないのだが、裏では動いているという理解でいいと思う。

そのほか

そのままでは機能はしないが、メニュー構造もできている。

つまり、プロジェクトを作成しただけでも、デスクトップアプリに必要な機能はほぼ提供されているのだ。

 

(続く)

C++ の -> と .

オンラインコンパイラー便利ですね。

けっこう使うようになりました。

そういえば、Objective-C で -> や . の取り扱いってどうなんだっけ?と疑問に思ったんだが、まずは C++ で復習。

以下のような簡単なサンプルを書いてみる。

#include <iostream>
#include <string>

struct sample {
int number;
char chara;
};

int main()
{
struct sample s1;
struct sample* s2;
s2 = &s1;

s2->number = 123;

std::cout << "s1 number= " << s1.number << std::endl;
std::cout << "s2 number= " << s2->number << std::endl;

}

今回、使ったオンライン環境はこちら

結果は以下のようになった。

世の教科書の教え通り

通常の構造体への変数として定義した s1 のメンバー変数にアクセスするときは . (ドット)

sample 構造体へのポインタ変数として定義した s2 のメンバー変数にアクセスするときは -> (アロー)

でうまくいく。

 

MoltenVK を試してみる

MacOS では将来的には OpenGL は廃止になる。

アップル公式的には、Metal を使えということになっているのだが、いやー、これがとっつきにくい。

Metal に被せる形にはなるのだが、Vulkan という仕様がある。

Vulkan の MacOS 向けの実装が MoltenVK で、GitHub にも公式リポジトリがあり、誰でも利用可能だ。

自分でビルドする必要があるが、大して難しくない。

MoltenVK のビルド

必要なのは cmake と python3 。

リポジトリからソースを取ってきた後、フォルダに移動して

./fetchDependencies --macos

を実行するのみ(iOS で使いたい人は –ios などとする)。

これで、Package/Release/MoltenVK に MoltenVK.xcframework ができている。

不幸にも

tool ‘xcodebuild’ requires Xcode, but active developer directory ‘/Library/Developer/CommandLineTools’ is a command line tools instance

のエラーが出た人は、ここらあたりを参照して直しておきましょう。

デモの実行

デモも用意されている。

実行すると

というウィンドウが表示されます。

ライブラリなどの構築

フレームワークがあるので、必ずしも必要ではないが、静的・動的ライブラリをアプリに組み込んで使いたい人は、.dylib や .a ファイルを作成する手段がいくつか提供されている。

わかりやすいのは、Xcode を使う方法でしょうか。

落としたてきたフォルダの中にMoltenPackaging.xcodeproj があるので、これを Xcode で開く。

プラットフォーム毎にターゲットが用意されているので、欲しいプラットフォームのターゲットを選び、ビルドする。

そんなに時間もかからず、ビルドは完了する。

まあ、現時点ではそんなに使う機会もないかな。

なお、公式のプログラミングガイダンスはこちら

けっこう、えぐい。

 

シェル芸

MacOS/iOS プロジェクトが初学者にとってとっつきにくい理由の一つは、突如としてシェルスクリプトの知識が要求されることではないだろうか?

アプリにしてもライブラリにしてもユニバーサルファイルを自動で生成してくれる機能はなく、arm64 向けにビルドしたものと x86_64 向けにビルドしたものを lipo コマンドで自分で一つにする必要がある。
この時、大抵の場合、「このシェルスクリプトを使え」みたいな案内があるが、初学者がその内容を把握できるとは思えない。

ここら辺までやるなら、いわゆるシェル芸の習得に時間を割いた方がいいと思う。

で、シェル芸なんだが、まとまった教科書なんてないでしょ?

まあ、教科書で覚えるもんでもないか。
わからなくなったら、その都度、検索かなあ。

ところで、シェルスクリプを書くにあたって、まず押さえておきたいシェルコマンドは、set かなあ。

書きたいシェルスクリプトの冒頭を

#!/bin/sh

set -e
set -o xtrace

としておけば、エラーで中断・内容を出力してくれるので、便利です。
どうせ、一発で動くことなんてほぼないんで(笑)