なるようになるかも

力は多くの場合、その人の思いを超えない。

Swiftは結局どうオープンソースになったのか?

オープンソース化ばんざーい!!とかそういうのは全然興味ないです、ごめんなさい。

XCode7で何気なくimport Foundationなどをすると、ついでに以下のライブラリがリンクされるそーです。

  • SwiftCoreSwiftのコア言語仕様)
  • DarwinUNIXベースのOSX/iOSの基盤部分。CoreFoundationもここに含まれる)
  • DispatchGrand Central Dispatch
  • CoreGraphics(描画処理の基盤部分。今はOpenGLだと思いますがそのうち中身がMetalになるのでしょうね)
  • ObjectiveCObjective-Cランタイム関数)
  • Security

Swiftオープンソース化される、と言っても本当にpure Swiftコンパイラだけが提供されてもあまり意味がないので、「どこまでがどうオープンソースになるのか?」というのが興味の焦点だったかと思います。

UIKitAPIを呼び出すだけで簡単にアプリケーションを作れるiOS開発とは別物になる」、というのはまず前提として、

  • Darwinの互換実装までが提供される。いまいち誰得な言語になる。
  • Foundationまでが提供される。ObjectiveCの呪縛から逃れられない。

の2択かなーと思ってたのですが、

  • CoreFoundationLinux実装と、その上に Swiftで書かれたFoundation を提供する。

という意外な答えでした。

Swift自身でFoundationを記述している、というのは興味深く(普通のSwiftObjective-CFoundation実装を利用しているだけなので)、ここがオープンソース版との一番の違いになると思います。

Foundationの行方

github.com

を見てみると、アプリケーションフレームワークの基礎として今後もFoundationを生かしたいというようなことが書いてあります。ただ、掲げられているゴールはちょびっと変わっています。

  • Make software development easier by introducing consistent conventions for things such as deallocation.
  • Support Unicode strings, object persistence, and object distribution.

が、

  • Make software development easier by introducing consistent conventions.
  • Support internationalization and localization, to make software accessible to users around the world.

にそれぞれ変わっています。

前者はメモリ管理がARCになったことで「例えばメモリ解放のような」という喩えの意味がなくなったからでしょうか。ARCでもメモリ管理を意識しないと簡単にリークするのは変わらないので、別にそこ変えなくてもよくない?と思うのですが。

後者はNSStringはUTF16のラッパー実装でしたが、今のUnicodeコードポイントは絵文字の侵食で21bitになってたり、オブジェクトをシリアライズして永続化するという発想そのものが時代に合わなくなってきたので表現を変えた感じでしょうか。

NSUnimplemented()で検索検索っ。

なお、現在のオープンソースSwiftFoundationは未実装な部分が多かったり、Objective-Cランタイムには存在するクラスがなかったりします。

以下のような注意書きがあります。

Important: This project is in the early stages of development. It is not yet ready for production use, but it is ready for contributions. It is scheduled to be part of the Swift 3 release.

<私訳>

重要: このプロジェクトは開発の初期段階にあります。これはまだ製品での使用はできませんが、コントリビューションの準備は整っています。Swift 3のリリースの一部として予定されています。

動的型付けを生かしたクラスクラスタの仕組みなんかは抹消されるんでしょうかね。SwiftにはKVCがないので、それを土台にしているKVOもありません。さらにKVOの上に乗っかってるCocoa Bindingsは時代を先取りしすぎた感じですね。

一方で、NSZoneのような今や無意味なクラスが生き残っていますが、これは「最初の1年はFoundationの可搬性を実現することに注力し、その目標と相反するAPIのビッグバンを回避する」というような意味合いがあるみたいですね。

Foundation without Objective-C runtime

This project provides an implementation of the Foundation API for platforms where there is no Objective-C runtime. On OS X, iOS, and other Apple platforms, apps should use the Foundation that comes with the operating system. Our goal is to abstract away the exact underlying platform as much as possible.

<私訳>

このプロジェクトは、Objective-CランタイムのないプラットフォームのためのFoundation APIの実装を提供します。OSXiOS、その他Appleのプラットフォームにおいては、アプリケーションはオペレーティングシステムに付属しているFoundationを利用するべきです。我々のゴールは、可能な限り精密な基盤となるプラットフォームを抽象化することです。

現状では、OSXでFoundationが不完全なオープンソースSwiftを使う意味はないので、XCodeで使えばいいってことですね。

これが現状だけを指すのか、Objective-Cランタイムを必要としないFoundationをオープンソースで開発し、いずれOSXiOSもそちらに移行するのでしょうか…?

さよならNSプレフィクス

ところで、このリポジトリの文章は全部面白いので読んだほうがいいです。すでにバイナリのあるコードをビルドするより有益な情報が得られます。いくつか面白かったところを取り上げます。

API Naming and Foundation

One of the goals of the Swift 3 project is a new set of naming guidelines. The Foundation project will soon update all of its names to match the new guidelines. We will also drop the 'NS' prefix from all classes.

<私訳>

API命名規則とFoundation

Swift 3 プロジェクトのゴールのひとつとして、命名規則の一新があります。Foundationプロジェクトはいずれ新しい命名規則と一致するように、全ての命名が更新されるでしょう。加えて、全てのクラスから'NS'プレフィクスを取り除きます。

FoundationSwiftで再実装して、その上に載っているフレームワークも全部作り直すのでしょうかねぇ。値型のSwift Arrayと参照型のNSArrayはどういう区別になるんです?

How do we decide if something belongs in the standard library or Foundation?

In general, the dividing line should be drawn in overlapping area of what people consider the language and what people consider to be a library feature.

For example, Optional is a type provided by the standard library. However, the compiler understands the concept to provide support for things like optional-chaining syntax. The compiler also has syntax for creating Arrays and Dictionaries.

On the other hand, the compiler has no built-in support for types like NSURL. NSURL also has ties into more complex functionality like basic networking support. Therefore this type is more appropriate for Foundation.

<私訳>

どのようにして標準ライブラリまたは、Foundationのいずれに属するものだと判断すればよいですか?

一般に、言語の機能の一部だと考える人々と、ライブラリの機能であるべきだと考える人々を重ね合わせた境界で分割されるべきです。

例えば、Optionalは標準ライブラリで型として提供されています。しかし、コンパイラはoptional-chaining構文などをサポートするためのコンセプトを理解しています。コンパイラはまた、配列や辞書を生成するための構文を持っています。

一方で、コンパイラはNSURLのような型は組み込みでサポートしていません。NSURLは基本的なネットワークのサポートなど、より複雑な機能との関連性を帯びます。よって、この型はFoundationの方がより相応しいです。

Swiftにおける標準ライブラリは現状に近いミニマルな構成のまま、Foundationに機能を持たせていくみたいですね。Swift 2でNSURLに関連付いたNSStringメソッドStringの拡張に含めるのをやめましたが、NSURLFoundationのものだから標準ライブラリからは隔離したい、というような意図だったのでしょうか。(参照型であることを前提にしているNSPathStore2を値型のStringにキャストすることで起きるパフォーマンス劣化回避が目的だと思っていたのですが)

Why not make the existing Objective-C implementation of Foundation open source?

Foundation on Darwin is written primarily in Objective-C, and the Objective-C runtime is not part of the Swift open source project. CoreFoundation, however, is a portable C library and does not require the Objective-C runtime. It contains much of the behavior that is exposed via the Foundation API. Therefore, it is used on all platforms including Linux.

<私訳>

なぜ既存のObjective-CによるFoundation実装をオープンソースにしないのですか?

Objective-Cおよびそのランタイムで書かれたDarwinのFoundationは、Swiftオープンソースプロジェクトには属しません。しかしながら、CoreFoundationは可搬性のあるCのライブラリであり、Objective-Cランタイムを必要としません。これにはFoundation APIを通じて公開されている振る舞いの多くが含まれています。そのため、Linuxを含む全てのプラットフォームで使われています。

Objective-CのFoundation実装を公開すればいいじゃん?」っていう疑問は、「それはSwiftのプロジェクトとは関係ないから」という正論で一蹴していますが、Foundationを別のオープンソースプロジェクトにすればよかっただけな気もするのですよね。

Swiftオープンソース化はそこから言語コミュニティが活発化してSwift 3へ進化することで結実するって感じなのですかねー。

そのときSwift 2.Xの資産は全てゴミになると思われますが…。

すたっく・おーばーふろー

blog.jnito.com

12位に載ってたので。

おそらくStackOverflowに多くの人が求めているのは「高品質なナレッジ」であり、そのため情報は英語に集約されるべきで、日本語版は不要という考えが強いと思うので、天邪鬼な自分は気ままに回答してます。

ところで、StackOverflowの本質というのは、その質の高いQAを支える コミュニティが存在する ところで、それ自体は日本語圏にもあっても良かったのになーと思います。

というより、10年くらい前のはてダ界隈がたぶんそんな感じだった気がします。適当な技術知識でモノを書くと手斧が飛び交っていましたが、異なる視点で技術論を交わしているのは見ていて非常に面白かったです。

もっとも、自分は一応はてなダイアリー評議会とかがあった頃に、はてなダイアリー市民だったのですが、当時のidは技術的なことをネットに書こうというモチベーションはなかったので見ているだけでしたけど。

かつて存在していたモヒカン族の掟は以下のようなものでした。

校正
間違いを訂正してくれる人を我々は尊敬して評価します。よけいな裏読みをして「人格攻撃している」とは思いません。
共有
アイディアに校正の機会を与えることが生みの親の義務です。「理由が無いけど、これはこれでいいんだ」というエレガントではない開き直りはくだらない。
ツッコミビリティ
校正、反論しやすいエレガントな言説が価値ある言説です。その為には、冗長にならない範囲で、ソースと推論過程を明確化し他へ示します。
全体最適
たくさんの人がハッピーになれるエレガントな方法を見つけた時、我々は最もハッピーになります。
差異
お互いの違いを確認することで、我々はつながります。「自分らにとって良いから他の人にも良いはずだ」とは思いません。
モヒカン族 (ネット用語) - Wikipedia

「社交辞令は抜かして端的に論点を述べる」とか「正しい情報に対して尊重する態度を持つべき」というモヒカン思想を、システム化し、コミュニティが支援しているのが英語版StackOverflowだという新説を唱えてみます。

それを実現させた背景は、Joel氏というカリスマの存在が大きいのでしょうけども。

日本語でおk

以下、全然関係ないんですけど、日本だと分散している日本話者によるQA系サイトで自分が見かけるもの。

MSDNフォーラム

Windowsプラットフォームの質問はほぼここに集約されている気がする。

MS社員(MSFT)やMVPプログラム受賞者(MVP)の回答があるため、回答の速度と質は物凄く高い。

Oracle Technology Network (OTN) Japan - 掲示板

とっくに閉鎖されていて、情報としては古いのですけれど、OracleJavaについて検索すると頻繁に引っかかる。

フォーラム全体としては微妙な空気ですよね。移行先はどうなってるんでしょう?

QA@IT

StackOverflowとほぼ同じシステム。人口も日本語版StackOverflowと拮抗してる?

StackOverflowやQiitaはWeb系開発者寄りだけど、こちらは業務系やインフラも扱っている印象。

teratail

コミュニティの重要度に目を付けながら、当初のログイン実装がセキュリティ的に端的に言ってゴミで、ギークな人は敬遠している印象。

StackOverflowだと「主観的な意見しか集まらない」でクローズされるような相談事も受け付けている。

その他

  • 知恵袋はオールジャンルなので案外質問されている。プログラミングカテゴリもある。ただしコードのシンタックスハイライトがないので読みづらく、回答がない質問は一定期間で消えるので実態がいまいち分からない。学生がC言語の宿題をそのまま質問にしている傾向があるような…。
  • OKWaveも技術者向けカテゴリがある。こちらもシンタックスハイライトがないので読みづらい。回答率はあまり高くなさそう。
  • 人力検索はてなはなぜか「ウェブ制作」限定になっている。なんで?はてな記法が使えるのでコードは読みやすいですよ。
  • 2chに初心者向けのプログラミング質問系のスレがあったりする。プログラム板で一番勢いがあるのは、C++相談室。

iOS9広告ブロック騒動雑感

煎じすぎて味がしないかもですが、開発者視点の話ってあんま見ないので。

Appleは日本の広告業界なんて見ていない

「悪い日本の広告が駆逐されるのは良いことだ」「これをいい機会に広告産業を見直すべきだ」的な論があるのだけれど、Appleは特に日本の広告業界について不満があるわけでもなんでもなく、ウェブサイトのネイティブアプリ化、あわよくば自社のiAdを盛り上げたいという意図しかないのでは?と考えています。

ウェブサイトのネイティブシフトについては、iOS8からSafariのログイン情報を使ってシームレスにアプリにログインする機能が追加されています。OSXではSafariでログインし、その認証情報をiCloudキーチェーンでiOSに連携、ネイティブアプリを使う、という囲い込みがAppleの考えているゴールと考えています。

情報を囲われるということは、広告産業にとって致命的です。リスティング広告ビッグデータ機械学習が輝いている分野の一つだと考えていますが、それを支えてきたのはオープンウェブの存在です。Appleがユーザーの行動情報を寡占すれば、それらの価値は大きく毀損し、同時にiAdの真価を発揮させていくのだと思います。たぶん。

こっから後はどうでもいい話です。

広告産業とアプリ開発

iPhoneアプリが流行っていた初期って、CoreMotionを使ったどうでもいいようなアプリにも100円で払える雰囲気があったと思うんですよ。連日ストアの上位を覗くのが楽しかったころです。

そういう時代には、アプリの売り上げで一発当てることも可能でした。その頃の人たちはもうコモディティ化したiPhoneには興味をなくして、ドローンでも飛ばして遊んでたりするんでしょうか。

ともあれ、そこへ広告産業が流入してきました。

アプリにお金を払う敷居ってやっぱり低くはないので、評判の良いアプリが一点集中的に売れる傾向にあったと思います。売れないアプリはさっぱり売れません。

ですので、売れないアプリのLite版を出して、広告収益に切り替えるところが増えていきました。

こうなると買い切り型のアプリはデメリットばかりが浮き彫りとなっていきました。iOSはバージョンアップで劇的にAPIが変わるので、それに追従する工数を捻出しなければならないのですが、既存のユーザーに負担を強いることはできないので、赤字覚悟で新バージョンに追従するか、買ってくれたユーザーを切り捨てるかの辛い二択になります。もはや市場には無料化したアプリが溢れているので新規開拓の望みも薄いのです。

この辺りで、「アプリを買う」という文化は廃れました。焼畑に広がるのは「OSをアップデートしたら起動しません。★1です」の怨嗟のレビューばかりです。

広告収益を上げるには、まずダウンロードされ、繰り返し起動されることが重要です。お小遣い稼ぎやアダルト系、2chまとめ系アプリのような、ウェブでも悪貨と言われる側が圧倒的に有利です。アプリのプロダクトデザインもユーザーゴールの実現よりアプリの消費期限の延命を、利便性よりもインプレッションを増やすための通知を送るよう、全てが改悪されていきます。追い打ちをかけるように、アプリ内課金型のソーシャルゲームがネイティブに流れてきました。

個人開発アプリの行方

もはや面白いアイデアを実現するアプリを作る開発者を応援することにジュース1本分のお金を払う価値は、出るか出ないかわからないSSSレアのために1万円払うことより低いわけです。

そういうわけで個人開発アプリのほとんどは、広告に頼っています。大きく当たることはないと思いますが、お小遣い程度の額にはなるんだと思います。その原資はどこから来ていたのかといえば、皆様の嫌いな「悪い日本の広告」です。

アプリ広告はウェブの広告と無関係でしょうか。そうは思いません。少なくないアプリ広告は起動時にブラウザを開き、サードパーティCookieを利用してユーザーを特定する仕組みを持っています。インストールしているアプリやウェブサイト閲覧などの傾向を蓄積し、ウェブブラウザの広告を最適化していると考えるのはそれほど突飛ではありません。どんな検索ワードに価値があるのか、どんな属性のユーザーがこの広告に食いつくのか、そういった情報はそのままお金になるのです。

よって、仮にスマホへの広告出稿が減るとすれば、そのダメージはGoogleやウェブ界隈だけではなく、個人開発アプリへも及ぶと考えます。

最新のMacBookを購入し、AppleWatchを肌身離さず、WWDCのために渡米し、iPhone6Sの予約を済ませあとは発送を待つばかり、開発者ライセンスを毎年更新し、Swiftコンパイラが吐くバイトコードと対話できるような、典型的なAppleユーザーですら広告ブロックの鉄槌を逃れられないのです。

いま、Swiftの登場によってアプリ開発の敷居は著しく下がり、XCodeも無償で実機で試せるようになり、過去最高に個人開発の機運が高まり、ここ数年で最も独創的なアプリが誕生すると言われていますが、果たして…。

擬似乱数というかarc4random()の話。

擬似乱数と言えば、かのカルドセプトサーガの悲劇が有名です。

ダイスの出目が必ず奇数と偶数の繰り返しになるという、地味ながらゲームバランスの根幹を破壊するバグが話題となりました。しかしその話題から得るべき教訓は、

その論調は一様に、サイコロすらまともに作れないなんて馬鹿すぎる、担当プログラマが低脳すぎて笑える、といったような物だった。やがてそのような書き込みの中に、Cコードを示して「サイコロなんかたったこれだけで作れるのに」と発言する者が何人か現れた。そしてこれが最も重要な点だが、そのようにして示されたコードは、なぜか全部カルドセプトサーガのプログラマが犯したのと同じミスを犯していた。

真の低脳は意外なところに潜む - うさだBlog

擬似乱数の特性について、正確に把握しているプログラマはあまりにも少ない、という事実だと思います。

とあるiOSの入門書では、arc4random()の呼び出しにsrand()が必要かのような記述が放置されていました。

その本はiOSのバージョンが上がる度に追従して改訂している本だったため、いつこの記述が修正されるのか毎年楽しみにしていたのですが、結局サンプルコードがSwiftに書き直されるまでの3~4年、間違った記述のまま直されることはありませんでした…。

乱数の種類と特性

良い乱数・悪い乱数を読めば終わる話なので深入りはしません。

真性乱数

現実世界でサイコロを振った場合の出目は、本当の意味のランダムなので、計算機が作り出す乱数と比較して、真性乱数と呼ばれたりします。

高度なセキュリティを要求されるケースでは、真性乱数を生成するために専用のハードウェアが用いられることがあります。

擬似乱数

計算機が算出するものは「次の値が予測可能である」という点において乱数とは言えないので、擬似乱数と区別して呼ばれます。

Cの標準ライブラリであるrand()が生成する乱数列は、ほとんどが線形合同法を利用した低い品質のものであることが多いのです。これはC99標準が乱数の強度に関する規定を行っていないこと、また線形合同法があらゆるハードウェアで高速で動作する実装であることなどが理由かと思われます。

計算機による擬似乱数は、再現性のある乱数列を生み出せるという特徴を持ちます。これは一見すると欠点のように思えますが、特定のシードを与えることでゲームの難易度を調整できたり、シードとユーザーの入力を記録するだけでリプレイデータを作れるなど、うまく使えば利点にもなります。

ただし質の悪い線形合同法によるrand()の実装では、下位1ビットが同じものが出続けるか、0と1の繰り返しになることがあります。ゲームでの乱数として用いる場合、下位ビットを切り捨てて使うのが当たり前でした。

これがカルドセプトサーガが犯した過ちですが、意外にプログラマをやっていてもこうした「お約束」を理解している人は少ないのではないでしょうか。rand()エントロピーを凌駕して、真性乱数を生成すると思い込んでいる方が少なくないように思います。

メルセンヌツイスター教に入信しておけば、おおむね問題ないと思います。

暗号論的擬似乱数

乱数の品質は計算量や出目の偏り、周期の長さで評価されることが多いのですが、それとは別に暗号用途で利用できるかどうかという軸があります。

通常の擬似乱数は、例え乱数列として品質が良くとも、暗号用途としては決して使ってはいけません。

両者を区別する、面倒な数学的な定義がありますが、「現実的な時間を掛けても、それが真の乱数列なのかアルゴリズムによって生成された擬似乱数なのか識別できない場合に暗号論的擬似乱数と呼ばれる」…程度のゆるふわな認識でいい気がします。

厳密な定義は人によって様々で怖いです。(メルセンヌツイスタで作った擬似乱数に暗号学的ハッシュ関数を掛けたものは暗号論的擬似乱数と言えるのか?とか)

arc4random()って何?

iOSでの開発では、arc4random()関数を用いて乱数を生成することが多いと思います。

これはお手軽に暗号論的擬似乱数列を得られます。

この関数はFreeBSD由来と言われることが多いのですが、manを読めば分かるように大本はRC4です。

RC

ロナルド・リン・リベスト氏という暗号分野で著名な研究者がおり、RC4は氏の作成した暗号アルゴリズムです。RCとは「リベスト暗号(Rivest Cipher)」の略だと言われており、RC1、RC3など開発中に解読されて欠番となったものもありますが、RC4やRC5、RC6などシリーズ化しています。

このネーミングでピンときた方がいるかもしれませんが、MD2やMD4、MD5の作者でもあります。

ARCFOUR

RC4は1987年にRSAデータセキュリティ社で開発され、そのアルゴリズムは長らく企業秘密でした。

しかし1990年代末に、ニュースグループにてその実装が解説が流出したことで、インターネットで公知なアルゴリズムとなりました。

こうして、RC4のオープン実装である、ARCFOUR(Alleged-RC4、「RC4以外の何か」)が普及しました。arc4random()もその実装の一つでした。

RC4の終焉とarc4random

現在ではRC4への攻撃方法が発見され、もはやセキュアではないといわれており(HTTPS通信におけるRC4の使用が禁止されるなど)、NetBSDなどのarc4random()の実装も、ChaCha20によるものに置き換えられています。

OSXiOSarc4random()は、まだRC4モドキらしいですが…。

そんなわけで、玄人はきっと/dev/randomから暗号論的乱数列を取得できるSecRandomCopyBytes()を使っているんだと思います。これがまた超使いにくいんですよね…。

追記

上の内容は、OSX 10.10のターミナルでman arc4randomした内容/dev/urandomでS-Boxを埋めてから、ARC4ストリーム暗号を使って乱数生成している)を元に書いていますが、Appleが公開しているLibc-997.90.3のソースコードではS-Boxの生成に/dev/randomを利用しているみたいです。

その後はARC4を使っていますが、脆弱性対策として最初の1024byteを捨てたあと、1600000byte毎に/dev/randomから再度シードを与えてるっぽい?

iOS/OSXカーネルにおいて/dev/randomの実装がどうなっているのかも興味があるところです(FreeBSDだと/dev/random/dev/urandomシンボリックリンクだったりするので。英語版のWikipediaの/dev/randomの記事ではiOS/OSXはYarrowアルゴリズムを使っているとあるけれど、この記述は古いような気がします)

iOS9 SDKでDeprecatedになるもの。

UPDATE(2015/09/26):この文書はDeprecatedという単語の使い方が雑なのでDeprecatedになりました。

こちらの記事を参照した方が得るものがあるかと思います。

qiita.com


新しいAPIの誕生より、APIの滅びの方が好きです。なぜならそこには失敗があり、学びがあるからです。

developer.apple.com

…とか適当に言ってみましたが、iOS9のAPI Diffは、Swift2.0絡みの変更点(主にNSErrorに対応するenumの追加と、後述するビットマスクの扱いの変更)だらけで、本当に変わった場所がどこなのか分かりにくいので、ちゃんと調べてないです。

AudioUnitがOSXに追いついたCoreAudio周りが熱いような…。CFunctionPointerの魔窟だったCoreMIDIなんかは刷新と言っていいレベルで変わっていますね。でも今のAppStoreでオーディオ系のアプリに対価を出す人がいるのかっていうと、微妙なんですよねぇ。

ところで、APIDiffはFrameworksModulesに分かれているのですが(両方読む必要があります)、Frameworks側の記述はヘッダーファイルレベルの記載なのでObjective-Cになっていて、Modules側はSwiftで書かれていて、読み辛いことこのうえないです。

なぜこんなことになっているのかというと、フレームワークのヘッダは、SwiftとObj-C向けで共用するために、Obj-Cの形式になっているからですかねー。(Swift用のヘッダは、XCodeが動的に変換を掛けている)

RawOptionSetType

NS_ENUMマクロで定義されたenumSwiftでも素直にenumになるけれど、NS_OPTIONSマクロで定義されている場合にはRawOptionSetType構造体に変換される、という特殊ルールについてご存知でしょうか。

Swiftのswitch-caseのパターンマッチングの強力さと、enumを組み合わせた安全性は言語仕様の魅力のひとつなのですが、素朴なビットマスクには弱いのです。

しかしご安心下さい。Swift2.0ではOptionSetType構造体がその座に取って代わります。これはSetAlgebraTypeプロトコル(SetAlgebraは集合代数の意味)に準拠しており、ビットマスクを扱いやすくするメソッドが追加されています。また独自のビットマスクを定義することも簡単になるみたいです。

独自のRawOptionSetTypeや、RawOptionSetTypeのextensionを作っている人は今のうちにこっそり削除しましょう。

AddressBook/AddressBookUI

滅亡します。

これはSwiftから使うのが辛そうな(そもそも可能だったんでしょうか?)APIだったので、順当に死にましたねーって感想。

Contactフレームワークがaddedになっているけれど、実際にはAddressBook内部で使われていたCNContactが機能拡張されて表に出てきて、AddressBookUIに対応するContactsUIが追加される形になっているような気がします。

新しいAPIはモダンで綺麗で素敵なんだろうなー!!と思ってみてみたら、NSPredicateを使うのかなこれ…。

stringByAddingPercentEscapesUsingEncoding

誰もが一度はこのメソッドに騙され、URLエンコードに失敗したのではないでしょうか。

:/エンコードしてくれない存在意義がいまいち良く分からないメソッドでしたが、ようやくiOS9で廃止されます。

今後は、iOS7以降のみ使えるstringByAddingPercentEncodingWithAllowedCharactersが推奨されます。これも正しく使わないと変換できませんが。

iOS6以前からやっていた人や、互換性を意識していた人はCoreFoundationCFURLCreateStringByAddingPercentEscapes()関数を利用していたかと思いますが、これもiOS9で廃止されますので注意が必要です。

結構使われてそうな関数なのでちょっと意外です。ARCの概念を知らない人が使うとメモリリークするから?

Java版Foundationのこと、覚えてる?

qiita.com

素朴な疑問があったので投稿してみました。これはその補足みたいなもの。

CoreData

CoreDataって凄く独特な世界観を持っていて扱いづらいと思った人が多いのではないでしょうか。

なんでこんなのがXCodeやInstrumentsのテンプレートに居座っているのか理解できない、関連張ると動作が重くなりすぎて使い物にならない、CoreData内部の良く分からないエラーに悩まされている、普通にSQL書きたいからFMDB使ってます、幻滅しましたRealmに移行します、そんな雰囲気だと思います。

CoreDataの原型は、NeXTのFoundationが用いられた最初の製品であるEnterprise Objects Frameworkです。

20年前にデータベース製品の学習コストの高さと、オブジェクト指向言語とのインピーダンスミスマッチの問題に取り組んだこの製品は、普及はしませんでしたが思想的な面などでは高い評価を得たそうです。AndroidのORMは栄枯盛衰でどれを使えばいいのか悩むのですが、iOSにはEOFの血脈を受け継いだCoreDataがいるのです。感動的ですね。

WebObjects

まぁCoreDataは本気でどうでもよくて、その原点たるEOFを発展させた世界初のWebアプリケーションフレームワークWebObjectsというNeXTの主力製品がありました。

これは「WWW経由でRDBMSからオブジェクトをフェッチし、HTMLにレンダリングする」という雰囲気の、こちらも概念としては面白いフレームワークで、主にエンタープライズ向けの製品だったので一般にはほとんど普及しなかったにも関わらず、コアなファンがいるとかいないとか。いないかも。

Apple内製では未だに現役みたいで、例えば今でもAppStoreはWebObjectsで動いています。

Java Foundation

WebObjectsもNeXT由来なのでObjective-Cで書かれていたのですが、Javaに完全移行した時代がありました。

全てをFoundationに依存していたWebObjectsが、Javaへ移行するために取った手段が、Foundationのクラス群をそのまま同名でJavaに再実装するという暴挙でした。

これは現存するJavaDocを読むと面白いです。中核技術だったKeyValueCodingの扱いとか、セレクタはReflectionだったりとか、カテゴリに相当する機能は実現できなかったりとか、ArrayListではなくNSArray使わなければならないとか。(KVOプロトコルのリファレンスに、「キー値監視はJava Applicationでは使えない」って注意書きがあるのもこの辺の名残だと思います、これいつ消えるんだろう…)

com.webobjects.foundation (WebObjects 5.4.2 Reference)

この前例を見る限り、「Foundationが徐々にSwiftのように洗練されていく」という可能性は低いかなーと思っています。

他言語に移植・移行するには、Foundationの持つ機能は、Objective-Cの言語仕様そのものすぎるのです。また、依存している多くのフレームワークが影響を受け互換性を失うデメリットと釣り合わないと思いますし、Swift型推論による安全な静的型付け言語であることを選択し、Smalltalk由来の動的型付けの機能を喪失したことも、移行を阻害する大きな要因になると思っています。

とはいえ

今からObjective-Cを書くのは半分くらいは技術的負債だと思っています。

KVCのせいで実質的にprivateなインスタンス変数は作れない、高速列挙プロトコルとか記憶から抹消した方がマシ、blocksにGCD、weakにnullableにGenericsと詰め込みすぎてもう意味が分からない言語になってます。

一方で、Core系のAPIを使うにはまだまだC互換言語の知識が捨てられません。

Swiftは当初、「Objective-C without the C」と大々的に宣伝されました。自分はこのフレーズにとても期待しましたが、Swiftでも関数ポインタが絡むAPIの辛さは軽減されないどころかむしろ酷くなっていて、特にクロージャを関数ポインタに逆変換する術がなくて詰むことが多いです。CFuntionPointerUnsafeMutablePointerで頑張るくらいなら普通にObjective-Cで書いた方がはるかにマシという感じです…。

とはいえSwift移行の大号令は近いうちにかかるでしょう。ただしそのとき殺す相手は、LLVM中間コードによるネイティブ並の動作を謳う、RubyMotionやXamarinのようなプロダクトなんじゃないかなぁ、その方がAppleらしさを感じます。

逆にSwiftがグダってくれれば、高級言語選択がもっと自由になるのかも。

Nexus5にAndorid M Preview入れた。

あるいはAndroidのデータ領域についての話。もしくはLollipopのバッテリーイーターに対する愚痴。

「Previewを入れるには全てのデータが消える覚悟が必要」みたいな話をよく聞きますが、Androidのデータ構造を理解せずに、batやシェルスクリプトを使ってアップデートをしている人の勘違いです。

前提条件はありますが、ユーザーデータ領域を残したままM Previewを入れることはできます。

Androidのデータ領域について

fastbootコマンドはおまじないではありません。データ領域の意味が分かれば、何をしているのか理解できます。

データ領域名 説明
bootloader fastbootモードで起動するのがこのブートローダ…みたいな認識で合ってるんでしょうか。通常oemロックにより読み取り専用領域となっていますが、Nexus端末はアンロックできます。ブートローダーのアンロック時には端末データが全部消し飛ぶので、一度アンロックしたら放置してます。
radio 通信領域に関わるファームウェア。「ベースバンド」という言葉が良く使われます。
boot boot領域です。Linuxカーネルと初期RAMディスクに相当します。bootとbootloaderはよく混同されてる気がする。
recovery リカバリ起動を行うための領域です。OSが起動不可能になった場合に、修復を行えるようにするため、OSとは別系統のシステムが存在するのです。必要最小限の構成のため、中身はほぼbootと同じらしいです。root化とカスタムリカバリのインストールもよく混同されてる気がする。
system Android OSのうちカーネルを除く部分(要はユーザーランド)です。システムはユーザー権限で動くので、root化するにはカスタムリカバリを用いてsuをインストールする方法が採られます。
userdata ユーザーデータ領域です。この領域を消さなければ、OSのみをアップデートすることができます。初回のOS起動時に既存のユーザーデータの最適化を行ってくれますが、挙動がおかしくなる場合もあるようです。その場合は諦めましょう。
cache 一時的なキャッシュとして利用される領域です。

flash-allがやっていること

fastbootにはいろいろコマンドがありますが、書き込みを行うflashと、削除を行うeraseだけ覚えとけば問題ない気がします?

flash-all.shの中身を見ると以下のような感じです。

fastboot flash bootloader bootloader-hammerhead-HHZ12h.img
fastboot reboot-bootloader
sleep 5
fastboot flash radio radio-hammerhead-M8974A-2.0.50.2.26.img
fastboot reboot-bootloader
sleep 5
fastboot -w update image-hammerhead-MPZ44Q.zip

まずブートローダーを書き換えて、続いてベースバンドバージョンを上げます。

fastboot -w updateというコマンドが出てきます。-wオプションは、userdatacacheeraseすることを意味します。その上でupdateコマンドで、zipファイルの中身をflashします。

image-hammerhead-MPZ44Q.zipの中身を見ると、

  • boot.img
  • recovery.img
  • system.img
  • userdata.img
  • cache.img

があります。それぞれが上表のデータ領域に相当しています。

ユーザーデータ領域を残したままAndroid Mに入れ替える

前提として、ブートローダーをアンロックしたまま利用している必要があります。ブートローダーのアンロックに伴う端末初期化は回避する方法がなさそうです。

fastboot flash bootloader bootloader-hammerhead-HHZ12h.img
fastboot reboot-bootloader
fastboot flash radio radio-hammerhead-M8974A-2.0.50.2.26.img
fastboot reboot-bootloader

ここまでは公式の方法と同じです。あとはimage-hammerhead-MPZ44Q.zipを解凍して、

fastboot flash boot boot.img
fastboot flash recovery recovery.img
fastboot flash system sytem.img

だけやれば、データを移行してOSだけアップデートできました。

cache領域のeraseは、やった方がよさそうですが、今のところやらなくても支障はありません。root権限があるなら、fastbootコマンドを使わなくても、単に/cacheの中身を消せばいいです。

Lollipopのバッテリー問題

Android Mはバッテリーの持ちがよくなる」みたいな話があります。アップデートした理由はほぼこれに尽きます。

条件が謎なのですが、Lollipopは一旦バッテリーイーターなモードに入ると、何もしなくても大体10~12時間くらいで電池が尽きるようになるのです。

f:id:quesera2:20150530163809p:plain:w300

頻繁に通信しそうなアプリは、Gmailを除いて消したのですがそれでもこれです。「その他」が電源をガリガリ削っています。同じ条件のiPhone 5Sは90%くらい残ってます。

当初、バッテリーがへたれたのかと思って新品に換えたけど意味がありませんでした。Nexus 5の電池交換はY字精密ドライバと、両面テープで張り付いてるバッテリーを剥がす根気が必要で、無駄に面倒です。

f:id:quesera2:20150530164955p:plain:w300

Android Mにして様子見てる感じでは上の通り真っ当な電池の減りです(Wifiのアイコンが塗りつぶされてるのはバグっぽい…iOS7で良く見たやつだ…)。バッテリー効率が改善されたというよりも、L Previewから放置されてきたバグをやっと直した、って感じがします。