環境
macOS Big Sur 11.6
方法
以下のコマンドで確認できる
$ sips -g hasAlpha filename.png
/path/filename.png
hasAlpha: yes
アルファチャンネルがない場合は hasAlpha: no
になる
macOS Big Sur 11.6
以下のコマンドで確認できる
$ sips -g hasAlpha filename.png
/path/filename.png
hasAlpha: yes
アルファチャンネルがない場合は hasAlpha: no
になる
言語プロセッサの勉強に、途切れ途切れではあるが Swift コンパイラにコントリビュートしてみたり、 Writing An Interpreter in Go を写経してみたりしていた。
そんな折、Rui Ueyama さんが 低レイヤを知りたい人のためのCコンパイラ作成入門 という平易な文章で1からCコンパイラの実装を解説したページと GitHub のリポジトリを公開してくださった。
取り組んでみたいが、読み進めるとLinux と macOS でアセンブリが完全互換ではないため、Mac ユーザは Linux 環境を用意した方が良いということが分かった。 そこで Docker を使って Mac で 9cc をビルドする環境を作ったのでメモを残しておく。 (なお筆者に Docker の実務経験はないのでもっと良い方法があるかもしれないとエクスキューズしておく。)
Docker で Ubuntu のイメージを pull する
$ docker pull ubuntu:18.04
Docker の image が取得できていることを確認
$ docker images
前述の docker images
で取得した IMAGE ID を使ってコンテナを起動する
Ubuntu の root にログインできる
$ docker run -it {IMAGE ID}
必要なツールをインストールする
以下 Ubuntu のイメージで実行
$ apt-get update $ apt install sudo $ sudo apt install gcc make git binutils libc6-dev vim
GitHub にコードを push したいので ssh の鍵を登録する
この辺を参考に Dockerで作るGitHub環境 - Qiita
以上で 9cc を開発できる環境が一応整った。時間を見つけて少しずつ進めたい。
Playground を使って UI の実装をしたら便利かつとても簡単だったので備忘録として。
普段書き捨てのコードやコーディングクイズの問題を Playground で実装するというのはよくやるのだけど、UIの実装で使うというのはほとんどやったことがなかった。ここでいう UI というのは UILabel や UIButton などの UI コンポーネントを指す。
なぜ Playground を使って書くかというと、Playground はコマンド一発で View の確認ができるのがとても手軽だから。アプリのプロジェクトを何回もビルドするのは時間がかかる。特に大きいプロジェクトでは余計に。またシミュレータや実機で確認するにしても、アプリが起動してから動作確認したい画面まで遷移するというのも手間で時間がかかる。Playground を使えば見た目がすぐに確認できるのでフィードバックループを小さくできる。確認の手間を小さくして、何度もチェックできるというのが良いところだと思う。「手動で動作確認をする代わりにユニットテストを書き、フィードバックループを小さくして何度も "チェック" する」というのはよく言われることだけど、それと同じだと思う。
Xcode 10.2.1
Xcode -> File -> New -> Playfround -> Single View を選択
すると以下のコードが自動生成された Playground ができる
Playground Driven Development (Xcode 10.2, Swift 5 ...
ここでポイントになるのは最後の行で、 PlaygroundPage.current.liveView
にセットした ViewController や UIView を Playground の live view ですぐに見ることができる。
PlaygroundPage.current.liveView = MyViewController()
いつも通り UI コンポーネントを実装する。Playgroundの同じページに書いていって構わない。
Command
+ Option
+ Return
で live view を表示できる。Command
+ Shift
+ Return
で実行できる。
Playground Driven Development で調べるとより詳細な方法が出てきた。
ここまで行けると良さそうだけど、シンプルな UI コンポーネントの実装であれば、 ViewController に addSubview() して見た目を素早くチェックする → コードを変更する → チェックする → コードを変更する ... というループを素早く回せればそれだけでも充分良いかなと感じた。
最近時間が取れる時に LeetCode をやっている。LeetCode はアルゴリズムの問題を解ける Web サービスで、課金するとシリコンバレーの有名企業のコーディングインタビューの過去問が解けたりもする。*1
自分が普段一番使うプログラミング言語が Swift なので、LeetCode でも Swift を使っている。解答例やフォーラムがあるので解けなかった問題はそこで答えを確認できるのだが、 Java や C++ の実装で for 文を使ったもが多い。Swift には C 言語や Java でいう for ループがない。*2
そこで代わりに使えるシンタックスがないか調べていたら stride(from:to:by:)
というのが標準ライブラリにあった。
iOS アプリの開発をしていて行き詰まると Google 検索することがよくある。というかほぼ毎日やっている。検索結果として Stack Overflow や Qiita, 個人のブログ記事を見つけて、困っていた問題が解決する場合がある。解決したい問題がフレームワークやライブラリの仕組み上必要なバッドノウハウだったりすればそれで構わない。しかし特定の API について体系だって書かれたドキュメントを読んで知識を得たい場合、正しい使い方を知りたい場合、知りたかった内容が必ずしも得られるとは限らない。その場合、適当にググって見つけた記事を読むよりも効果的な方法は以下の 2 つになるような気がしている。
基本的に公式の情報は全てここにある。ただ自分としては、初心者にはいまいち知りたい情報を探しにくいし取っつきづらいと感じている。
そこで Apple のエンジニア直伝の開発ドキュメント検索方法。昨年 WWDC のラボで
「 developer.apple.com って初心者にはいまいち知りたい情報を探しにくくないですか?例えばあなたはどうやってドキュメントを調べていますか?」
とApple のエンジニアに質問してみた。すると、そのエンジニアはそれは課題だと感じていて、 Google のサイト内検索機能を使っていると教えてもらった。
Google で検索したい内容を入力する時に、検索バーに site:https://developer.apple.com
と入れることで、サイト内検索をすることができる。
例えば URLSession
について調べたければこんなかんじ。
同じように Xcode でドキュメントを調べることもできる。(Xcode 10.1)
Xcode を起動 -> Help -> Developer Documentation
実際に動くコードの例を探したいことは良くある。その場合に考えられるのが以下の方法。
GitHub には世界中のエンジニアが書いたライブラリやフレームワークのコード、定番ライブラリを組み込んだアプリのコードがたくさん公開されている。これらは未経験の開発言語やフレームワーク、新しいライブラリを使う場合とても参考になる。検索ツールを使えば、言語や公開時期など細かい条件を指定してコードを検索することができる。
GitHub · Where software is built
Apple Developer にも動くプロジェクトとしてサンプルコードが公開されている。ぱっと見探しづらいが以下の方法で調べることができる。
前述と同じ方法。
site:developer.apple.com Sample Code
と入力する。
以下の Documentation Archive の Sample Code にも色々まとめられている。
忙しいと Google 検索して済ませがちだけど、やはりオフィシャルのドキュメントにはフレームワークの正しい使い方が書いてあるし、実コードを手元で動かしたり、様々な使い方を目にすることで自分のコードに活かせる新しい発見がたくさんあるように思う。
CircleCI 上で実行した $ fastlane deliver
で
Multiple App Store Connect Teams found; unable to choose, terminal not interactive!
というエラーが出た。
先に結論を述べると、職場で利用している Apple Developer Program のアカウントが複数のチームに紐付いていたのが原因だった。 最近 Enterprise アカウントを作成したことの副作用で発生した出来事だった。
解決方法としては、deliver のパラメータに Team ID を明示的に渡してやる。Deliverfile に書いてやるのが簡潔で良い。 ちなみに自分のプロジェクトで使っている Deliverfile は以下の通り。内容は一部改変している。
app_identifier “jp.foo.bar" username “buz@example.com" team_id “xxxxxxxxxxx" force false skip_screenshots true skip_metadata true skip_binary_upload false automatic_release false
ちなみに1点気をつけることがあり、この時 Team ID として入力するのは、 Developer Program で確認できる 10 桁の Team ID ではなく、 Spaceship で取得できる数値。 fastlane が実行できる環境であれば、irb も Spaceship を使えると思う。以下のように取得する。
$ irb irb> require "spaceship" irb> Spaceship::Tunes.login("iTunesConnect_username", "iTunesConnect_password") irb> Spaceship::Tunes.select_team
Xcode 10.1, Swift 4.1
iOS アプリ開発において、 Web API にリクエストするモジュールのユニットテストを書くことは良くあると思う。その場合 Web API にそのままアクセスするテストを書くと、返す値によってテスト結果が変わる脆いテストになってしまう。そのため Web API の戻り値をスタブして、 実際には HTTP リクエストを行なわないというのが基本になる。
HTTP リクエストをインターセプトして、任意の値を返すために使うライブラリは kylef/Mockingjay, AliSoftware/OHHTTPStubs 辺りが定番で、僕は Mockingjay を好んで使っている。Mockingjay のインストール方法は GitHub の README.md を参考にしてほしい。また、Web API の戻り値を json に肩代わりさせるが、その方法については以前書いた Qiita の記事に詳しい。
iOSプロジェクトのテストバンドルに存在するファイルを取得する - Qiita
以下の extension を用意することで、呼び元で簡潔にスタブすることができる。
呼び元のコードはこのように書く。XCTest を使う場合も呼び方は変わらないが、非同期のテストを書く場合少し工夫が必要になる。
ユニットテストに限らず、本質的にやりたいことを実現するためにはどうしても煩雑なコードが必要になる場合がある。コードの保守性を高く保つ為には、複雑性を隠蔽して明解なインターフェースに落とし込み、呼び元のレイヤを簡潔に保つことが必要不可欠になる。