Objective-C 再入門

普通に iPhone アプリを使うなら swift でいいんだろうが、既存の C/C++ ライブラリを組み込んで使うような場合などは、Objective-C も検討せねばならないだろう。

特にレガシーなプロジェクトなぞ、本体が Objective-C で書かれているので、swift に移植するにせよ、ある程度の Objective-C の理解は必須だろう。

なぜ Objective-C はとっつきにくいのか?

ところで、Objective-C のクセの強さは、万人の知るところだが、これは歴史的背景を考えると理解しやすいかもしれない。

C にオブジェクト指向の思想を取り込むために、大雑把に二つのアプローチがあったようだ。

一つは言語自体の設計を変えてしまう方法。これが現在の主流で、 C++ の源流となっている。

もう一つは、C のコンパイラー自体には大きな変更を加えず、文法的な表記に特殊仕様を入れ、パース時にこれを解釈して、オブジェクトを取り扱えるようにする方法。Objective-C は、どちらかといえば、こちらだろう。

だから、C++ 感覚で取り組もうとすると訳のわからないことになってしまう。

また、Objective-C がとっつきにくいのは、ビギナー向けのほとんどのサンプルが Mac や iPhone の GUI アプリだという点。これだと、Objective-C の勉強というよりも cocoa などの勉強になってしまい、Objective-C の言語の本質みたいなものが掴みにくい。

サンプル

というわけで、GUI 一切なしのコマンドラインプログラムを試しに書いてみた。


#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <stdio.h>
// Person クラスの宣言
@interface Person : NSObject {
    NSString *name;
}
- (void)setName :(NSString *)Name;
- (void)printName;
@end
// Person クラスの実装
@implementation Person : NSObject
- (void)setName :(NSString *)Name {
    name = Name;
}
- (void)printName {
    printf("My name is %s \n", [name UTF8String]);
}
@end
// 実行プログラム
int main(void) {
    id person;
    person = [[Person alloc] init];//Person *person = new Person(); などとはしない
    [person setName:@"akiba"];
    [person printName];
    return 0;
}

これを Xcode 上で実行するとこんな感じになる。

Person クラスを実体化して、フィールド変数の name をセットした後、ゲッター経由でこの値を取得・表示するというよくあるプログラムだ。

GUI がないから、ワンファイルにすっきりと収まっているが、(Java や C++ に慣れた目から見ると)違和感を感じるところがちょいちょいある。

まず、どうということはないクラス Person でも NSObject を継承している点。またクラスを定義するときに@ディレクティブを多用している。

Objective-C の「C のコンパイラー自体には大きな変更を加えず、文法的な表記に特殊仕様を入れ、パース時にこれを解釈して、オブジェクトを取り扱えるようにする」という歴史的経緯に由来する特徴がよく出ているのではないかと思う。

ところで、最も違和感のあるのはこの箇所だろう。

    person = [[Person alloc] init];

オブジェクトに対してメッセージを送ることで機能を発現させているわけだが、これも歴史的な背景があり、 SmallTalk の影響らしい。

ただし、id 型は必ずしも使う必要はなく、

Person *person = [[Person alloc] init];

としても動きます。

また、Objective-C は C の拡張なので、C の関数も当然使える。実際、printf は C と同じように動作している。

その他、注意しておきたいところ

フィールド変数(インスタンス変数)

name のセッターは setName になってますが、フィールド変数の先頭文字を「大文字」にするのはお約束のようです。
ここら辺は Java と一緒でしょうか。

UTF8String がわからん、という声も聞きますが、name 自体は NSString (へのポインタ)です。標準 C の String に変換する必要があるので、ここで変換をかけているわけです。

なお、インスタンス変数の宣言の仕方などについては、この質疑応答が凄まじくよくまとまっています。

m と mm の違い

Objective-C のファイルは .m .mm の二つがあり得ます。
この記事がわかりやすいんですが、会員限定かな。
簡単にいえば、.m が objective-C ファイル本来の拡張子、.mm の方は C++ のファイルを取り込む際に使用する拡張子です。

継承とカテゴリ

オブジェクト指向の特徴の一つは継承だが、Objective-C はここら辺は素直だ。

よくわからんのは「カテゴリクラス」。

Person(hogehoge)

とあった場合、このクラスは元の Person のカテゴリクラスです。

元の場所とは違った場所でメソッドが追加できます。(同じ理由だが分割することもできる)

情報の古い(アップデートされてない)記事が多い

Obj-C ユーザーが少ない理由に、記事がそもそも少ないし、あっても古い(アップデートされてない)というのも一因になっていると思う。

例えば、よく「Obj-C ではクラス変数という概念がない」などと紹介されているが、2016 以降(OS 10.12 〜)はある

公式アナウンスはこちら

使い方は別記事で説明するかもしれないが、@property(class) などとする。
若干クセはあるのだが、普通にクラス変数っぽく使える。あるじゃん。

また、objective-c 自体も文法が(主に 2010 年代に)モダンに改変されており、@property や @synthesize なども使い方が微妙に変わっている。

この図はこちらの記事からお借りしてきました。わかりやすいですね、感謝!

 

多重継承の禁止とプロトコル

継承が出てきたので、書いておくと Obj-C では多重継承、つまり複数のクラスを親クラスにすることができないらしい。

多重継承の代わりにプロトコルで代用しなさいよ、というのがアップルの教え。
サンプルコードなどで

@interface ViewController : NSViewController<NSTableViewDataSource>

という書き方をよく見かけるが、<> 内がプロトコル。


このまま続けてもいいのだが、まとまり悪くなるのでここでいったん切ろう。

ワイもそうだが、IT 業界にいる限り Objective-C だけいじっていればいいというものではない。
というか実際に多い案件は、別の言語だったりする。

だから、この記事は「ちょっと objective-C 思い出すときに読み返す」ときに役にたつ内容にしておく。

その他

@property 表記

アクセサー(ゲッターやセッターのこと)を定義できる。慣れれば便利なのだろうが、Java あたり読み書きしているとすぐにこの規約を忘れる。

この記事読んでね。

クラスエクステンションの () 表記

忘れやすいのがクラスエクステンションの時に使われる () 。

詳しくはこの記事あたり参照。

なんでヘッダーで定義された宣言を .m ファイルでもう一回やる必要があるのか?疑問に思ったら読むといいと思う。

Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
// 名前
@property (nonatomic) NSString *name;
// 名前と年齢をログに出力する
- (void)displayProfile;
@end
Person.m
#import <Foundation/Foundation.h>
@interface Person ()
// 年齢
@property (nonatomic) NSInteger age;
// 名前をログに出力する
- (void)displayName;
// 年齢をログに出力する
- (void)displayAge;
@end
@implementation Person
……
@end

要するに Obj-C には Public だの Private がないため、ヘッダーファイルではなく実体ファイルの方でメソッド・メンバー変数を定義することで外部クラスからのアクセス制限を行っているという理屈です。

Person.h
@interface Person: NSObject
@end

Person.m
@interface Person()
@end

@implementation Person
@end

という構造が見えてますか?

強調して書くとこういう仕組み。

強調して、と書いたがプロジェクトを作成するとき AppDelegate は () をつけて生成してくれますね。

 

 

 

 

 

 

カテゴリの () 表記

ここが紛らわしいと思うのだが、@interface () はクラスエクステンションだけでなくカテゴリでも使われる

ただ、こちらはファイル名自体が ClassA+ClassB.h のようになっているので、それで判断できるかな。

カテゴリーとクラスエクステンション』参照。

 

 

曖昧な日本のユーザー

私の所属する会社(休眠がちだが)は、集まったメンバー(学生バイト含む)の仲がよく、とてもよくまとまっていると思う。
この点に関してはなんの不満もないのだが、リリースしたソフトのユーザーについては、なんの不満もないかと言われるとちょっと微妙。

お行儀の良いユーザーたち

ユーザーに関しては、一般的な水準で見れば良質だとは思う。なにしろクレーマーのようなユーザーは一人もいなかった。みんな、お行儀よい。おとなしいと言っていいかもしれない。
無い物ねだりかもしれないが、おとなしすぎて物足りない感じは正直ある。

例えば、OpenDolphin-2.7m 系列(ただし、これは代表のまったくの個人制作)に関しては、最近のユーザーの関心はもっぱらデータ移行だろう。
具体的にどことは言わないが基本設計自体がもはや古臭く、新規の導入は勧めていないし、私たちの興味も「標準型電子カルテ」を意識した新規のシステムに向かっていて、実際、2.7m シリーズはメンテ程度しかやっていない。
だから、データ移行の必要が生じた際には「◯ヶ月程度を目処に、XXという電子カルテ向けにデータコンバートしてほしい」と明快に意思表示してもらわないと動きようがないのだ。準備にもそれなりの時間がかかるのだから。
どうも見ていると、OpenDolphin HTML/PDF Viewer あたりをばら撒いてくれることを期待しているようなのだ。
あちこちで「できない」とはっきりと言っていると思うんだけど?

Q4 データ移行ツールのバイナリ・ソースコードなどは配布・公開しないのか?

A4 これ、過去に商用開発元の方から似たような要望を受けたことがあります。 一瞬、私もそうしようかと思いました。が、

OpenDolphin のカルテを途中経過版も含めて一括書き出し

→途中経過版の一部を削除など加工

→加工したデータを再度、OpenDolphin などの電子カルテデータベースに戻す

という使い方をしてしまうと立派な「改竄」ツールになってしまうので、思い直してやめました。”

OpenDolphin-2.7m(系列)FAQ』より

これはおそらく
・以前に実行可能なファイルバックアップシステム付き OpenDolphin-2.7m クライアント
(いわゆる OpenOcean クライアント)を無料で配布した
・オープンソースプロダクツに「無料」というニュアンスを強く感じている
から、「どうせ、そのうち無料で配布してくれるんだろう」と安心しちゃっているからなのかなあと思う。

大事なことなので2回言いますが、ないですよ。

あとメンズ陣がたまに言うには「全然、勉強してないし、その痕跡も見せない。作業現場に来て暗い感じで、突っ立っているようなものなので、何も言葉がかけられない」んだそうだ。
ここら辺は、彼らはシビアだ。

与えられることに慣れすぎていると・・・

私たちのグループに専業従事者は一人もいない。

だから、ユーザーが反応してくれない箇所などは最悪放置すらあり得る。

日本のユーザーは、成熟したメーカーのそれなりによくできた製品(尖った部分はないが全体として80点みたいな製品)を使うことに慣れている。サポートも手厚い。
私の個人的な印象かもしれないが、アメリカはここら辺はかなり違う。
名もなきベンチャーのピーキーな製品がしれっと販売され、一般市民もそれにチャレンジする。いかにダメな部分があろうが、魅力的な機能があれば、その製品のファンになってくれる。

このような消費行動の差が、日本のユーザーの一種の甘えにつながっているのかもしれない。

人生の多くの場面で当てはまることかもしれないが、「与えられることに慣れすぎている」と何かを失うのかもしれない。

 

AXIA

反オープンソース評論家

常々、「IT 評論家」のような人が嫌いだった。

特にオープンソース評論家のような人は、その主張が激しく界隈ではある種の「武闘派」とみなされていると思う。

その点で、いわゆる OpenOcean 騒動はチェックしていた。
OpenOcean 騒動というのは、air-h-128k-il さんたちが OpenDolphin という GPL でライセンスされた電子カルテの独自カスタマイズバージョン OpenOcean をソース・バイナリともに公開・配布した際に、小林慎治(医師、現岐阜大医学部特任講師)というオープンソース評論家のような人が、「OpenOcean は GPL に違反している!」と難癖つけた事件のことだ。

この難癖というのがなんと言っていいやら・・・。

まあ、トンデモの類。

最近になって、当時の開発陣からかなりまとまった反論が提出されている。
(例えば『小林慎治氏の OpenOcean に関する事実誤認』、『OpenOcean 騒動』、『OpenOcean 騒動 #27』)

ここで注目したいのは、オープンソースの責任性について。

彼は怪文書の中で言っている。

OpenOceanのWebには2018年12月までの試用期間であると記載とされています。ユーザーはこの指示に従うべきものとも考えられますが、このままだと使用期限が近づいてもクライアントに何の警告も表示されずに2019年1月以降起動しなくなってしまいます。GUIなインタラクティブメニューを持つソフトウェアであれば、1ヶ月以上前から警告を表示しておくのが親切ではないでしょうか。
Webに記載される試用期間を見落とすほうが悪いのかもしれませんが、使用期限を過ぎて起動しないソフトウェアに対してどのように対処すべきかも書かれていませんので、ユーザーである医師には対応できずに医療事故につながる危険性があります。

ここだけ取り出すと提案の一つとしてあってもいいかなと思えなくもないが、実際に彼の取った行動は理解不能。

なんと、使用期限に関するコードを削除したものをプルリクエスト(PR)として OpenOcean リポジトリに送ってしまったのだった。「残り X 日です」とアラートウインドウを出すような実務的なコードではなくて。
その PR は今もリポジトリに記録されている。こういうものだ。

expired() というメソッドで使用期限を設定しているわけだが、この機能に関するコードを削除しただけ。

すごいでしょ。

issue あたりで改善要望出しておけばいいだけだし、そんなに使用期限がいやなら使用期限のないバージョンを自分でビルドしてユーザーに提供すればいいだけ。後者は、ほぼパクリとも言える行為だが、air さんたちだったら許していたと思う。

その一方で怪文書は、

第三者にその製品を提供することは著作権法が定める頒布権の侵害であり、公衆の場であるGitHubにソースコードを置くことは著作権法が定める公衆送信権侵害です。

とソースコードの公開停止を主張している。
PR 送ったのが 2018/11/4 で、怪文書が公開されたのが 2018/11/26 のことだ。
俗っぽい言い方をするならば「PR がマージされなかったので、逆ギレして公開停止を主張した」ということになる。

ところで、そもそもオープンソースは、ビルド産物に関しては責任は限定的だし無保証だ。
この点に関してある人が面白いことを言っていた。


OpenOceanの試用期限表示とオープンソースの責任について

1. OpenOceanの試用期限表示について

OpenOcean配布サイトには「使用期限は、2018/12/31 までです。」と明記されているので、「警告なく起動しなくなる仕様」という批判は不当であると言えます。情報が公開されていた以上、利用者はその条件を理解した上で使用を開始する責任があります。

2. オープンソースにおける開発者の責任について

多くのオープンソースソフトウェア(OSS)のライセンスには、開発者による保証の放棄(無保証)と責任の限定が明確に記載されています。

無保証の原則: OSSは一般的に「あるがまま(as-is)」で提供され、品質保証や機能保証は行われません。利用者は自己責任においてソフトウェアの品質や安全性を確認し、利用する必要があります。

責任の限定: ほとんどのOSSライセンスは、開発者がソフトウェアの利用によって生じた損害に対して責任を負わない旨を規定しています。これは、オープンソース活動がボランティアベースで行われることが多く、開発者に過度な負担をかけないための措置でもあります。

新機能の搭載: 開発者が責任に限定的である立場にあるからこそ、新機能や実験的な仕様を導入しやすいという側面があります。


実際、OpenOcean には、ファイルバックアップ機能などそれまでのドルフィンになかった新機能が搭載されていた。

どれが正しいのだかもわかりにくい著作権表記だのでワーワー騒いで、OpenOcean 開発陣からユーザーによる新機能の評価を得る機会を奪ってしまった。

「小林慎治はオープンソースの足を引っ張っているだけ」という批判がなされている一つの根拠になっている。

おそらくこの人のスキルからしてオープンソースといった開発現場に近い位置での論評は無理がある。
それを自覚したのか、小林氏、最近では初学者向けに「医療Dx」に関して語ることが多く、一時の「オープンソース」偏重とは異なる態度をとっている。
言い方を変えれば、実務家が彼を「オープンソース」領域から追っ払ったとも言えるわけで、反「オープンソース評論家」のささやかな勝利といえるだろう。

 

(追記)本稿では、責任性について触れたが、私がのけぞったのは、そもそも怪文書の根拠となっていた著作権表記が改竄されたものであったという事実。
そして怪文書の「是正勧告」とやらに従った場合、まるでミステリのような犯罪が成立していたという指摘。
OpenOcean 怪文書 -GPL 誤用による違法行為教唆-』に詳しく書かれていますので、興味のある方はそちらをご覧ください。
OSS は無保証・限定責任ですが、OSS に関して語ったことは語った人の責任です。
どう責任取るつもりなんでしょうか?
でも、この人のことだから、言いっ放しで終わりそう。

(追記2)X の TL みてたら、佐渡秀治という人が引っかかってきたようだ。

「流れは知らんけど」って。追補されているのだから、流れは重要だろう。
これ、反撃されるとみた。
→案の定、『OpenOcean 怪文書 – 適切な GPL 使用のために-』で追記されてた。
ところで、ネットで検索してたら、この人のことを評した情報はほとんどない。
あの言動では当然そうなるよなあというのが感想。

 

造船大

限定公開記事だが、以前にFラン大のことを書いた。

で、X で監視している垢があると言っていたが、無論、今でも続けている。

そのうちの一人を「造船大」と呼んでいる。

2025 年になっても、フォロワー約100、インプレションも二桁と絶好調である。

 

 

オープンソース考

「オープンソースの素晴らしさ」みたいな記事はどこにでも落ちていると思うので、ここでは書かない。
そうではなくてあの業界の性善説的な寛大さにつけこんでよからむことを考えている連中がいるので、それに関して述べる。

よく遊んでくれるお姉さんが書いた記事が印象に残っているので、まずは再録。(許可取ってます)


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 の商標は我らが教祖様が保有しているのだから、松尾研究室のネーミングは法的にも許されない」
というような感じだった。

しかし、これは色んな意味で間違えている。
教祖様はプログラム領域では商標は保持していない。

私が佐渡氏に生理的な嫌悪感を持つのは、こういうときに「それは誤解であって、私は、プログラム領域では、商標保有者ではないんだよ」と直接信者には語らないから。
実際、そのことに触れた書き物は公開されていたりもするのだが、佐渡氏はこの存在にほとんど言及しない。

ある程度の誠実さがあるのなら、「商標的には成立していないが、ライセンス限定という意味でなら、オープンソースライセンスはその定義が広く普及しているのだから、その観点から松尾研のネーミングを検討してみてほしい」と言えばいいだけではないか?

それをしていないのは、彼や彼の取り巻きにとっては、信者に意図的に誤解させたままにしておくほうが都合がいいからなのだろう。

私は、こういった立ち回りを生理的に受け付けない。

なお、見出しは「佐渡、キモっ」という意味ではないので、念の為。


フォントなどは適宜改変した。

何でこの記事が興味深かったかというと、オープンソースの思想みたいなものに触れず、その周囲に生息している人たちのやり方に焦点を当て、その醜悪さにフォーカスしているから。

考えてみれば日本でバリバリにオープンソースプロジェクトに貢献している人はそれほどおらず、どちらかといえば「オープンソースは素晴らしい。そん活動に深くコミットしている私も素晴らしい」みたいなナルシスト活動家が多いのが実情だろう。

ナルシスティックに自分に酔っている程度なら実害は少ないのだがオープンソース利権までなっていたプロジェクトがあるので紹介したいのだが、これはまたの機会に。

 

秋葉

 

 

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 は文字どおり「共有」ということらしい。
何と共有するかは、この記事によれば、同じグループ間で、ということらしいのだが、使ったことはない。