iOS開発に入門する
仕事では低レベルな方しか使わないので後回しにしてきたが、だいたいXNU周辺の事情は理解出来たのでアプリ側も覚えるかな、という気分になる。 といってもそんなにバリバリ開発する気は無くて、ちょっとチームメンバの作ったテストアプリにペインを足してデバッグ出力したり、とかその程度でいいかな、とは思っている。
Objective-C
以前OS Xでswiftをちょっと触った時に、フレームワーク周りの解説でちょこちょこObjective-Cにあたったので今回は簡単に入門しておく。 といってもそんなにはやる気は無いので「Objective-C for C++ programmer」とかでググって上の方に来た奴を適当に読む。
codeproject: From C++ to Objective-C: A quick guide for practical programmers
良くわからなかった所メモ。
@selector
がどういうものか良く分からない- allocの開きカッコが一つ足りないのはtypoっぽい(一貫しているが…)
- Categoriesと普通の継承のsyntaxの違いがよくわからない
一番最後のFurther Readingに貼られているpdfのうち、上記の分からない所を眺めてみるか。
selectorはp16のあたり。ざっと読んで理解する。
Categoryはp25あたり。わかりにくいが、p26の4.6を見ると普通のカッコでカテゴリを、angle braketでプロトコルの継承を表すっぽいな。
フレームワークを解読出来ればいいのでこの位の理解でいいか。
追記: 公式ドキュメントも読んだ。Programming with Objective-C。 ダラダラ続く感じではあるが読みやすい。
Swift
Swift実践入門
以前Swift実践入門を読んだので、この本を軽く復習しておく。(手元のは一つ古い版だが)
この本は変数名がintとかstringというややこしい変数名を使って混乱するのと、一部文法機能の解説で使われ方が良く分からない紹介の仕方をするので凄く良いとは思わないけれど、必要なことが一通り書かれてはいるので及第点と思う。
各項目のタイトルとコードの部分を読んでいって、理解出来ない所は解説を読む、みたいな感じで一日くらいで読む。 Kotlinと似ているのと以前いちど一通り読んだので割とすぐ読み終わる。
小文字のoptionalの解説が見当たらなかったが読み飛ばしてしまったのかな?まぁprotocolの必須じゃないメンバなんだろうが。
The Swift Programming Language
そのあと公式のGetting Startedから参照されていたThe Swift Programming LanguageのePub版を項目調べたい時には使っている。これが無料で公開されているのはいいね。 割と解説を読むタイプの文書で、リファレンスとしてはやや引きにくいけど文書内リンクが充実しているので困る事は無い。 以後はこれだけあればいいや。
Getting StartedのJump Right Inをやる
実際に何か書いてみよう。
とりあえず公式のGetting Startedがいいかな、ということで、公式のGetting StartedのJump Right Inというのをやってみよう。
料理レビューアプリみたいなのを作る、という奴。 master-detail型のCRUDで、普通のコントロール並べたり遷移書いたりと、カスタムコントロールとUITableViewがある。
1ステップ目: Build a Basic UI関連の感想
まずは最初のページの「Build a Basic UI」をやっていく。
AppDelegate.swiftを眺める
エントリーポイントはdelegateなのか。そしてatributeを指定するとアプリのmainを実行してこのdelegateにわたすのね。へー、かっこいい。 ここでApplicationが渡ってくるからこれで十分ってことね。
UIApplicationDelegateを Cmd+クリック で眺めてみるとactiveになる時やbackgroundに行く時などが来るっぽいね。なるほど。
UIScenenSessionとかのあるあたりは説明を読まないと分からなさそうだな。
解説を読んでいくとスタブ実装があると書いてあるが、無いな。別にいいけど、こんな一番最初のドキュメントのメンテが追いついていないというのはちょっと意外だな。iOSはそういうのしっかりしてると思ってたので。Androidではなにも珍しくないが。
UITextFieldを追加する
EditorからCanvasを選べ、というが、Editorってどこのことだろう? メニューにEditorというのがあるな。これか?Bounds Rectangle、チェックされてないな。チェックしてみよう。
次にObject libraryを開けというが右側のペインにはそんなの無いな。ただメニューのViewにShow Libraryというのがある。 なんか全然違う画面だが、まぁいいか。
そのほかViewをいろいろポトペタする。この辺はどこも一緒やね。
プレビューを見る
Assistant editorというのを出せ、と書いてあるが、そんなボタンは自分のXCodeには無い。ふーむ。 ただEdit Paneの右上の所のボタンを押したらAssistantというのはあるな。これか? ただ上のタブから指定されたPreviewは無い。
でもさっきの右上のボタンにPreviewというのはあったな。それっぽいのが出た。 うーん、なんかこのGetting Started、結構不一致があるなぁ。
最初のステップを終わっての感想
AutoLayout、まんまConstraintsLayoutだな。同じなのは楽で良いが。 ここまででだいたいUIのパーツをポトペタしてレイアウトするのは出来そう。 たぶんハンドリングもやれば出来ると思うので、ここまででもとりあえず何か書くことは出来そうだなぁ。
やってることは置いただけなので大したこと無いが情報量が多い。 普通の入門者じゃわからんだろう、という気もするが、まぁ今どきはどこかしらでは似たようなことやってる人も多いか。 完全な素人は分からないまま手を動かしてなんとなく分かっていけばいいかもしれん。
情報量が多いのは自分みたいなのがちゃんと知りたい時には非常に良い。だいぶ理解は深まった。 入門書読むよりはこれやる方が良さそうだなぁ。
2ステップ目: Connect the UI to Source Codeの感想
さて、次はイベントのハンドリングかしら。と読み始めると唐突にMVCっぽい話がダラダラと続いて、これは知らん人はぽかーんだろうなぁ、とか思うなど。 まぁMVC2くらいのwebよりあとで何かしらこの手の触ったこと無い人は居ないか。
TextFieldのドラッグアンドドロップ
Assistantにドラッグアンドドロップせよ、と書いてあるが、全然出来ないな。(普通にテキストフィールドがUIエディタから消える) あ、Ctrl押しながらか。なるほど。
Outletというのが出来た。これが何かは知らんがweak refなTextFieldへの参照なのでこれで触れるんだろう。
IBはInterface Builderか。そして突然はじまるweak refの説明。プログラム素人が入門するのは大変だなぁ(^^;
Outletという所にシステムはViewをセットするのだな。現時点ではDIされるそういう口のことをOutletと呼ぶと理解して先に進もう。
TextFieldのイベントハンドリング
ここまで来たらenterでtextFieldのtextからlabelのtextに代入するしか無いんじゃないか? と思うと、firstResponderなるものの解説が始まる。 focusとかactiveとかその辺の概念のiOS版っぽいな。
textFieldShouldReturnにまず反応してresignするとtextFieldDidEndEditingが呼ばれるのでこれで値を詰めろ、との事。 ShouldReturnの所でvalidationするのかしら?
ステップ2の雑感
とりあえずボタンを置いてテキストフィールド置いてイベントに反応する事までは出来た。 これで一通り簡単なGUIは作れるようになった。 ここから先はサンプルのコード見つつ適当なView調べるだけでも十分に思うが、 せっかくなのでStoryboard周辺の理解のためにもうちょっと進めてみる事にする。
この文書のGetting Startedとしての品質は高いと思う。 微妙に手元のバージョンとUIが違うが、それは書籍とかでも一緒だろうなぁ。 他の分野のGUIプログラムの経験があればこれで十分、と思う。 やり方が書いてあるだけじゃなくてどうしてそうなっているのかの背後の説明も、 入門者に必要な程度にされている。
一方でこれを理解するには結構な知識を要求されるなぁ、とも思う。 DIとかMVVMとか通常のイベントドリブンなGUIプログラムとかある程度知っていてSwiftもある程度知っていないと、どうしてそうなってるのかとかが分からない部分が結構ある。
iOSプログラムもAndroidプログラムも、今や意外と敷居高いよなぁ。
3ステップ目: Work with View Controllers
view controller間のデータのやり取りとかやるらしい。(追記: やらなかった!)
ImageViewを置いて画像を表示
ImageViewを置いて右側にペインが出ない。
メニューの View>Inspectors>Show Attributes Inspector
で出た。 なおObject libraryはCmd+Shift+L。
prsentとdismissはもうちょっと詳しい説明が無いとなにが起こっているか分からんねぇ。 modal的な概念があってViewControllerが管理しているのかしらね。
この関数を書け、はインテリセンスの方を信じる。 UIImagePickerControllerOriginalImageはUIImagePickerController.InfoKey.originalImageにrenameされた、とのツールチップが。 こういうのはいいね。
Info.plistに画像のピッカーのpermission要求みたいなの書いて画像のpickerを動かす。 delegateで受け取るのはasync世代にはちょっとダサいな。 ただ特に問題も無く終える。次に行こう。
4ステップ目: Implement a Custom Control
カスタムコントロールを作るらしい。 といってもUIStackViewを継承してコードの中から追加する程度。へぇ、UserControl的な概念は無いのかね。
ratingButtonTappedをselectorに追加するとObjective-Cにexposeされてないよ、と怒られたので、@objc
を追加しておく
@objc func ratingButtonTapped(button :UIButton) {
//...
}
これはドキュメントを直しておいて欲しいなぁ。
黒い星はiPadのデフォルトが黒なので見えないな。一番上のViewのバックグラウンドを白に変える。 ラベルの色も黒を指定。この辺は画像の色に合わせるとプラットフォームのデフォルトと変わっちゃう訳だが、どうするのが正しいのかねぇ。
一通り最後まで終わる。入門的なカスタムコントロールを作れるようになった。didSetとか使っていろいろやるのはswift wayだな。
5ステップ目以降
ここからはそんなに分からない事も無いのでこのページ的には小項目扱いで。
5ステップ目: Define Your Data Model
ここは特に分からない事も無し。Testing Frameworkは古臭いが、使えない事も無し。testable importはいいね。 やっぱ言語に支援が要るよなぁ。
6ステップ目: Create a Table View
テーブル関連はフレームワークの特徴が出る所なのでちょっと楽しみではある。 ストーリーボードの新たなシーンも作るという事でそれなりにやる事は多い。
この辺まで来ると作業が多い割には新しく学ぶ事は少ないので、Getting Startedという形式でやるのはかったるくなってくる。 手順の説明はたぶん読まなくても出来ると思うのだが、何か知っておくべき事が書いてあったら嫌なので一応読む、みたいになりがち。 これなら一通り普通の説明を読んでからまとめて自分で作業する方がだいぶ効率は良さそう。 まぁもうちょっと進めてみる。
tableViewは要素数とcellのインスタンス返す結構別の役割を引数のオーバーロードで同名で済ませているのか。これはどうなの?
追記: オーバーロードと考えずにtableViewに対する別のメッセージ、と考えるのかね。イディオム的に第一引数をselfとして捉えるという。ふむ。
そしてiPadのデフォルト背景が黒で星が見えない。 MealTableViewCellのバックグラウンドを白にしてラベルのテキストの色を黒にしたらだいたいいいのだが、空のセルの背景は黒になってしまうなぁ。 TableViewの背景を指定すれば白になりそうなもんなんだが、ならん。まぁいいや。
で、MealViewControllerにrenameするの、え?これ手作業でやらないといけないの?そりゃ無いよ。 泣きながら手作業で直す。普通の開発ではどうしてるのかなぁ、これ。
7ステップ目: Implement Navigation
ようやく遷移を実装する。このCtrl押しながらUI部品をエディタに置くのは完全自動よりもいいね。 segueというのをUIから指定する、というのはちょっと面白い。
SaveをDisableにするあたりからかったるくなり、ざっと説明を眺めたあとは自分でやってみて、分からない所がなかったら詳細は読まずに進む事にする。 最後まで進んで別段分からない事も無し。
8ステップ目: Imeplement Edit and Delete Behavior
To configure the table view cellでセルからMealViewConrollerへのsegueを貼ってタップしても全然反応しなくてハマる。 結局TableViewのUser Interaction Enabledをtrueにする、という事で解決した。 こんな所falseにした記憶は無いんだがなぁ。デフォルトが変わったのかしら?それともどっかで誤操作していたか? 階層が多くていろいろな所にInteraction Enabledがあって該当箇所を発見するのに苦労した。
こういう時はソースコードが無いのは辛いやね。そして公式のGetting Startedがメンテされてないので動くものと比較出来ないという辛さもある。
この辺まで来るとだいぶXCodeの操作には慣れてきたな。説明もあまり読まなくても作業が進められる。 Activityの遷移と似た感じよね。
9ステップ目: Save and Load the Meal
オブジェクトの永続化の話。 この辺は実際はいろいろな選択肢がありそうなので要るか微妙だが、 一応一つの選択肢を知っておくという意味でやっておく。
リンクされてるFile System Programming Guideは読んでおいた方が良さそうだな。あとで読もう。
でNSKeyedArchiver.archiveRootObject
は古いと言われるな。
NSKeyedArchiver.archivedData
を使えと言われる。
でもこれにはパスを渡す引数が無い。うーん。
なんか返ってきたdataに書くっぽいな。 archivedData 第二引数はfalseで良さそうか。
おや、throwsがついている、とか言われるな。 元のコードと同じ意味にするにはこんな感じか?
private func saveMeals() {
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: meals, requiringSecureCoding: false)
try data.write(to: Meal.ArchiveURL)
os_log("Meal saved", log: OSLog.default, type: .debug)
} catch {
os_log("Meal save fail", log: OSLog.default, type: .error)
}
}
よし、次はunarchivedだな。ってNSKeyedUnarchiver.unarchiveObject
も無いと言われるな。ではarchivedDataの反対は何を使うのがいいのかな?
NSKeyedUnarchiverを眺めると、unarchiveTopLevelObjectWithData
で良さそうかな。
だがdataはどうやって作るのだろうか。
ググって見た感じだと、Dataのコンストラクタを呼べば良さそうな雰囲気か?こんな感じか?
private func loadMeals() -> [Meal]? {
do {
let data = try Data(contentsOf: Meal.ArchiveURL)
return try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [Meal]
} catch {
return nil
}
}
動いてそうだな。この辺はちょっとドキュメントのアップデート欲しいね。といかdeprecatedにする時は解決策もAPI referenceにリンクしておいて欲しいものだが。
一通り終えてみての感想
標準的なmaster-detail型のCRUDアプリを作る、という良くある構成ではあるが、必要な事はだいたい含まれていたと思う。 最初に読むたぐいのドキュメントの割には解説がしっかりしていて、 「細かい説明はしないけどこういうものだと最初はコピペしといて!」みたいなのがあまり無い。 これはフレームワークが現代的だからという面もあるけれど、ドキュメントとして良く出来ていると思う。 入門書を買うよりは断然こっちの方が良さそう。
前提知識は結構ある気がする。 Swiftの知識はあった方が良い。そんな複雑な機能は使わないけれど。 iOSは素人でいいと思うけれど、いわゆるMVC2世代のフレームワーク(railsとかASP.NET MVCとか)は一つくらいは知ってる方が良さそう。 また、Androidで普段からConstraints LayoutとかLinearLayoutとかActivityとか触っている人じゃないと少し消化不良を起こすかも。 また、スマホのアプリにありがちな問題をある程度理解している方が書いてある事の裏を理解しやすい。 そうして考えるとこのドキュメントを読むのは結構ベテランである事が期待されているよなぁ。
それなりにまともなアプリを作るので、どうしても後半は細かな作業が多くなってしまって、 それがいちいち作業手順を全部書いてあるので進みが悪くなってしまう。 Getting Startedとしては手順が全部書いてあるのは大切と思うけれど、それにしてはやはり作業量が多すぎるんじゃないかなぁ、という気もする。 ただテーブルに出すくらいまでは割と良いので、その辺まで丹念に読みつつ進めたあと、 もういいかな、と思ったあとは解説を読み飛ばしつつ作っていけばいいんじゃないかと思う。
最新のXCodeで動かせないのはちょっと残念。 基本的にはインテリセンスからだいたい予想はつくのでトラブルが出た時と最後の永続化以外は特に問題無いと思うが、 トラブル出た時に無駄にトラブルシュートに時間が掛かる。
このGetting Startedだけで作りたい物は作り始められるかな、という気がする。あとはリファレンスだけでいいかなぁ。 そう思えるという事はこのGetting Startedに期待されている役割を見事に果たしているといえる。前提条件を満たせていればおすすめ。
このさきへのリンク
最後にいろいろリンクがあるが、そこに無い物や自分用メモとしていくつか貼っておく。
- Documentation Archive: UIKitカテゴリ 良質なドキュメントがいっぱいある。以後はこれでいいか、という感じ。UIKit以外のカテゴリも良さそう。
- Drawing and Printing Guide for iOS カスタムのViewでdrawRectを書きたい時用。
- Mac Technology Overview 割とiOSとも共通な部分が多いので、該当のレイヤ探すのに良い。
- File System Programming Guide ディレクトリ構造などは特徴的なので一度ちゃんと見ておく必要がありそうだなぁ、という事でリンク。
- String Progiramming Guide NSStringは良く使うので。
- UIKitのリファレンス App Programming Guide for iOSという名前でリンクを貼られているが実態はUIKitのリファレンスっぽい。ちょこちょこ概要的な事も書いてあるが、そんなに詳しくも無い。軽く眺めておくくらいかな。