J2ObjC は使えるか?
Java プログラムを Objective-C プログラムに変換してくれる天下のグーグル謹製プロジェクト J2ObjC 。
興味を持ったので試してみた。
何はともあれビルド。
ビルド
公式のページに従う。
注意点としては・・・。
PROTOBUF_ROOT_DIR=/usr/local
を .zprofile あたりに追記。この時に
PROTOBUF_ROOT_DIR='/usr/local'
とやってしまうと文字列と判定されてしまうので、ビルド途上でおこられます。
並列ビルドも失敗しやすいようなので、まず
make -j4 dist
と最低限のコンパイルを片付けてしまい、必要に応じて
make frameworks
make all_frameworks
とするといいと思う。
Hello World
ビルドはとんでもなく時間がかかるので、すぐにできる j2objc, j2objcc を使ってハロワしてみよう。
公式ページにある Hello.java
public class Hello {
public static void main(String[] args) {
System.out.println("hello, world");
}
}
を
j2objc Hello.java
すると同名の .m ファイル(Hello.m)ができる。
#define J2OBJC_IMPORTED_BY_JAVA_IMPLEMENTATION 1
#include "Hello.h"
#include "IOSObjectArray.h"
#include "J2ObjC_source.h"
#include "java/io/PrintStream.h"
#include "java/lang/System.h"
#if __has_feature(objc_arc)
#error "Hello must not be compiled with ARC (-fobjc-arc)"
#endif
#pragma clang diagnostic error "-Wreturn-type"
#pragma clang diagnostic ignored "-Wswitch"
@implementation Hello
J2OBJC_IGNORE_DESIGNATED_BEGIN
- (instancetype)init {
Hello_init(self);
return self;
}
J2OBJC_IGNORE_DESIGNATED_END
+ (void)mainWithNSStringArray:(IOSObjectArray *)args {
Hello_mainWithNSStringArray_(args);
}
+ (const J2ObjcClassInfo *)__metadata {
static J2ObjcMethodInfo methods[] = {
{ NULL, NULL, 0x1, -1, -1, -1, -1, -1, -1 },
{ NULL, "V", 0x9, 0, 1, -1, -1, -1, -1 },
};
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-multiple-method-names"
#pragma clang diagnostic ignored "-Wundeclared-selector"
methods[0].selector = @selector(init);
methods[1].selector = @selector(mainWithNSStringArray:);
#pragma clang diagnostic pop
static const void *ptrTable[] = { "main", "[LNSString;" };
static const J2ObjcClassInfo _Hello = { "Hello", NULL, ptrTable, methods, NULL, 7, 0x1, 2, 0, -1, -1, -1, -1, -1 };
return &_Hello;
}
@end
void Hello_init(Hello *self) {
NSObject_init(self);
}
Hello *new_Hello_init() {
J2OBJC_NEW_IMPL(Hello, init)
}
Hello *create_Hello_init() {
J2OBJC_CREATE_IMPL(Hello, init)
}
void Hello_mainWithNSStringArray_(IOSObjectArray *args) {
Hello_initialize();
[((JavaIoPrintStream *) nil_chk(JreLoadStatic(JavaLangSystem, out))) printlnWithNSString:@"hello, world"];
}
J2OBJC_CLASS_TYPE_LITERAL_SOURCE(Hello)
おお、Objective-C じゃん!
次に
j2objcc -c Hello.m
j2objcc -o hello Hello.o
として実行バイナリ hello をつくる。
% ./hello Hello
hello, world
おおお。
Java リバーシアプリを iPhone アプリに
そうこうするうちに dist フォルダに生成物ができていたので、これを利用して Xcode プロジェクトのサンプルを試してみた。
公式が Java reversi プログラムを Xcode 上でビルドするサンプルを紹介していたので、これにトライする。
ほぼそのままで動きました。
JRE.framework を JRE.xcframework にするくらいの変更でOK牧場。

すげ。
(続く)
オープンソース考
「オープンソースの素晴らしさ」みたいな記事はどこにでも落ちていると思うので、ここでは書かない。
そうではなくてあの業界の性善説的な寛大さにつけこんでよからむことを考えている連中がいるので、それに関して述べる。
よく遊んでくれるお姉さんが書いた記事が印象に残っているので、まずは再録。(許可取ってます)
OPENSAUCE/OPENSOURCE
X(twitter)の投稿はそんなに頻繁にしておらず、だから、バズるみたいな現象とは無縁なのだが、例外的にこのポストにはちらほら反応があった。

要するに
「OPENSAUCE 社が公開レシピのプラットフォームとして OPENSAUCE を商標登録しようとしたが、OPENSOURCE が既に登録されていたため、拒絶された。
が、OPENSOURCE の使用実態がなかったため、不使用取消審判を請求した。
しかし、この件を OPENSOURCE 商標を保持している OSDN 社及び同社代表佐渡秀治が、誤解を招くようにアナウンスしている」
というものだ。
詳しく知りたい方は、リンク先の OPENSAUCE 社のこのページからどうぞ。
これを見つけた時の私の第一感は、(ポストにもそのニュアンスは出しているが)「うわぁ、またやっているよ」というもの。
以下、ちょっとした感想。
松尾研究室オープンソースAI事件とその副産物
また、というのは、ちょっと前に(時系列的には、これより後なんだが)生成AIで有名な松尾研究室が、同研究室開発のソフトを「オープンソース」と広報したときに、オープンソースな方々が「Creative Commons ライセンスは OSI 基準のオープンソースライセンスに当てはまらないので、この AI はオープンソースではない」と騒ぎを起こしたことがあったから。
ちなみにこの騒ぎは松尾研究室が「オープンソース」の旗を下ろすことで幕が降りた。
個人的には、(この手の論争はよく起こることなので一定の結論を出すという意味で)もっとやり合って欲しかったのだが、そこまでには至らず、松尾研究室が大人の対応をすることでこの件はクローズとなってしまったのだった。
だが、論争相手が現在勢いのある松尾研究室であったため、いくつかの副産物が生まれた。
X(twitter)を漁ればわかると思うが、かなり優秀な人々がこの件に関してコメントしている。この点はいつもの「オープンソース」論争とは一味違っていたのだ。
副産物の一つは、「open source という単語は、OSI などオープンソース関連団体が特別な意味を付与する以前から、『ソースコードが公開されている』程度の意味合いで普通に使われていた」という事実が発覚したことだ。
open も source もごく一般的な名詞にすぎない。
「ソースコードが公開されている」程度の意味で「open source」という一般単語組み合わせワードを使うことは、商標が成立する以前から使われていたわけだから、仮に商標があったとしても、禁じることはできない、というように解釈するのが普通だろう。
もう一つの大きな副産物は
「そもそも、プログラム領域では商標自体が成立していなかった」
というかなり身も蓋もないもの。
拒絶された理由も、わかりやすく書けば
「open も source も一般的に使われている。それらを組み合わせた open source は特別な知識なしでも「ソースコードが公開されている」という意味に解釈できるよね。なんでそんなものに特別な権利を与えなきゃならんの?」
とかなり明快だ。
佐渡秀治氏の立ち回りが政治的すぎて生理的に受け付けない
松尾事件勃発直後の末端オープンソース信者のおおよその反応は
「オープンソースTM の商標は我らが教祖様が保有しているのだから、松尾研究室のネーミングは法的にも許されない」
というような感じだった。
しかし、これは色んな意味で間違えている。
教祖様はプログラム領域では商標は保持していない。
私が佐渡氏に生理的な嫌悪感を持つのは、こういうときに「それは誤解であって、私は、プログラム領域では、商標保有者ではないんだよ」と直接信者には語らないから。
実際、そのことに触れた書き物は公開されていたりもするのだが、佐渡氏はこの存在にほとんど言及しない。
ある程度の誠実さがあるのなら、「商標的には成立していないが、ライセンス限定という意味でなら、オープンソースライセンスはその定義が広く普及しているのだから、その観点から松尾研のネーミングを検討してみてほしい」と言えばいいだけではないか?
それをしていないのは、彼や彼の取り巻きにとっては、信者に意図的に誤解させたままにしておくほうが都合がいいからなのだろう。
私は、こういった立ち回りを生理的に受け付けない。
なお、見出しは「佐渡、キモっ」という意味ではないので、念の為。
フォントなどは適宜改変した。
何でこの記事が興味深かったかというと、オープンソースの思想みたいなものに触れず、その周囲に生息している人たちのやり方に焦点を当て、その本質的な反社会性のようなものにフォーカスしているから。
考えてみれば日本でバリバリにオープンソースプロジェクトに貢献している人はそれほどおらず、どちらかといえば「オープンソースは素晴らしい。そのような崇高な活動に深くコミットしている私も素晴らしい」みたいなナルシスト活動家が多いのが実情だろう。
ナルシスティックに自分に酔っている程度なら実害は少ないのだがオープンソース利権までなっていたプロジェクトがあるので紹介したいのだが、これはまたの機会に。
・・・などと言っていたのだが、その後も同じ調子でデジタル庁の資料を攻撃していた。
ただ、SNS 時代に彼のやり方はあってないフシがある。
IT 界隈の実務的なリーダー層を中心に「文意を汲み取れば、デジタル庁の説明はおかしくない。本来の目的である『各省庁が保有するソースコード資産の共有範囲を拡大するのか?するとすればどのようなやり方を取るのか?』という問題提起や議論の邪魔をしているだけではないか」というような指摘をする人が結構いた。
政治とマスコミの関係を見るまでもなく、多くの監視の目がある SNS の世界では、幼稚なスローガンを声高に叫ぶだけでは通用しなくなっている。
秋葉
NSUserDefaults
サンプル
AppDelegate.m
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; // 取得
[ud setObject:@"hoge" forKey:@"KEY_S"];
[ud synchronize];
}
参考:https://glassonion.hatenablog.com/entry/20110920/1316473990
保存場所
Non SandBox: /Users/ユーザ名/Library/Preferences
SandBox: /Users/ユーザ名/Library/Containers/アプリ名/Data/Library/Preferences/

なのだそうだが、デバッグ時にそれらしいファイルはなかったな???
→registerDefaults メソッドはファイルに書き出しません!
しかし、standard と shared の違いがわからんなあ。
→shared は文字どおり「共有」ということらしい。
何と共有するかは、この記事によれば、同じグループ間で、ということらしいのだが、使ったことはない。
Objective-C 諸々
objective-c や cocoa の割と独自仕様っぽいところ。
delegate
見かける割にいまいち理解できていなかったデリゲート。
「MTKView のデリゲートがレンダラー」と気がつき、ああそういうことかと納得。
大抵の場合、ViewController が MTKView を呼び出す前に
_view.delegate = _renderer;
などとしているはずだ。
メタルの表示用ビューとして MTKView は存在しているが、各アプリでのこのビューの使い方は様々だろうから、そこら辺は自分で DrawInMTKView を実装してね、プロトコルは準備しておくから・・・ということなんだと思う。
わかりにくくなるのは、プロトコルが明示されているわけではないので、その仕組みに気が付きにくいからじゃないでしょうか。
本来であれば以下のような記述が必要なようだ。
委譲する側(のヘッダ)
@protocol HogeDelegate
@property (weak, nonatomic) id delegate;
@protpcol HogeDelegate <NSObject>
-(void)FugaMethod;
@end
以下のように明示的にぶん投げるときもある。
委譲する側(の .m ファイル)
[self.delegate FugaMethod] //こうやって使うようだ
ぶん投げられる側はプロトコル準拠を明示しておく。
委譲される側(のヘッダ)
@interface Fuga: NSObject <HogeDelegate>
ところで、これが面白いのは、ある種の情報の通知として利用できる点。
上の例なら、Hoge の情報を Fuga で受けられる。
ViewerController に受け持たせてしまい、あるオブジェクトでの情報をビューに反映させるといった使い方ができる。
参考:https://dev.classmethod.jp/articles/ios-delegate/
マルチスレッド処理
NSTread を使う方法、dispatch_async – queue の系を使う方法などいくつかあるようだ。
(続く)
KVO
https://qiita.com/mitsu9/items/e738c41a8d87cc71ec3e
KVOとはキー値監視(Key-Value Observing)のことを指します。
アプリ開発をかじったことのある人ならMVCという言葉を聞いたことがあると思いますが、KVOはModelの変更をControllerやViewに通知し、反映させるための仕組みです。
他の通知システムとしてはdelegateやNSNotificationを利用した方法などがあります。
なるほど。
サンプルとして MCV を意識したメモアプリあり。
インスタンス変数の宣言
『Objective-Cでは、インスタンス変数をどこに宣言するのが正しいのか? 』が興味深かった。
やはり、みなさん疑問に思っていたんですね。
参考
phorlix100 の github issues 。
いやー、大変参考になりました!


