実機へのXcodeビルドが失敗したときに振り返ること
失敗は突如として起こる…
iOSのビルドが通らない、実機がつながらないなどにぶち当たり、一日潰してしまった…などということはないでしょうか? 残念ながら、わたしは多々あります…
起きるタイミングは?
コードが影響であれば、gitで切り戻したり、差分をstashすることで変更前を試せます。 それ以外では傾向として、Xcode・OSX(Mac)・iOSなどのアップデートをトリガーにすることが多いかと思います。
Xcodeに関しては開発作業前の対応が多く、OSXについてもXcodeとセットでの更新なので気づきやすいです。 ですが、iOSアップデートについては完全に意識から抜けていることが多いので、注意が必要!
iPhoneが認識されない?
デバイスが待てど暮らせど出ないと、ケーブルの断線など疑ってしまいがちです… ケーブルを2本も用意しておけば、この手の懸念はすぐに払拭できます。
さらにiPhoneのロック解除をしてみましょう。
- PCを信頼するか否か、ダイアログが出ている場合があります…
- 信頼するを選択すると出てきます。
Signingに関わるところは?
Signingの警告が消えないときがしばしばあります。 証明書にまつわる事象ですが、ローカルだけでなくApple Developerサイト側で対応が必要なケースがあるので注意が必要です。
- Certificatesの有効期限が切れていないか?
- Certificatesを参照可能なチームからはずれていないか?
- Devicesに実機のUDIDが登録されているか?
- ProfilesのDevicesにチェックは入っているか?
ローカル側でも設定を引けない原因となる可能性があります。
- Preferences > Accounts にAppleIDが登録されているか?
- KeychainにCertificatesファイルは登録されているか?
最近引っかかったのですが、Targetが複数あるプロジェクトだとビルド対象以外のTargetでSigningの警告がでていてもビルドできないケースがありました。
- すべてのTargetのSIgningが通っているか?
今後もこちらに知見を積んで行こうと思います。
Macbookを購入して最初にやること(メモ)
このページの内容
7年ぶりに新しいMacbookを購入しました! セットアップは非常に楽しい作業ですが、抜け漏れないようにやりたいので自分に向けてメモを残します。
手順
開梱・起動する。
インストール
- 何はともあれ、Xcodeをインストール。
- ダウンロードに時間がかかるため。command line toolsなど考えると必須。
- Chromeをインストール。
- Google日本語入力をインストール。
- VSCodeをインストール。
- Extension: Setting Sync を入れて設定を引っ張り出しておく。
- iTerm2をインストール。
システム環境設定
Dock: 右
キーボード: キーリピートを最速にする。
キーボード: スリープのショートカットを作成しておく。
キーボード: Google日本語入力を入れる。
ディスプレイ: 解像度を最高にする。
CUI環境
- 古い端末から以下をコピーしてくる。
.ssh
ディレクトリ下ファイル.gitconfig
ファイル
- プロンプトを見慣れた感じにする。
$ cp /etc/zshrc ~/.zshrc $ chmod 600 .zshrc $ vi .zshrc : PS1="[%n@%m %1~ ]%# " :
ssh github.com
を通しておく。ssh bitbucket.org
も通しておく。
キャプチャをJPEGに切り替える
OS標準のスクリーンキャプチャをPNG→JPEG保存に切り替えます。(容量が大きいので…)
% defaults write com.apple.screencapture type jpg
また作業が進んだら書き足します。
自社プロジェクトに xcprojectlint をかけてみた
知見が少なかったり、検証者がいなかったり、小さな開発現場は積極的にLinterを入れるべきだと思っています。
iOS開発をはじめてまだ1ヶ月ちょっとですが、まず最初にLinterを探しました。
プロジェクトのLinterを発見
引き継ぎプロジェクトが Objective-C
だったのですが、言語のLinterは良さそうなものが見つからず、代わりにプロジェクトのLinterを見つけました。
アメックスさんがオープンソースを公開しているとは知りませんでした。 こちらはSwiftで書かれておりMacでの導入も非常に簡潔で、さくっと仕掛けられました。
導入方法について
何人かの方がすでに書かれていたので、記事を拝見させていただきました。 こちらで事足りると思いますので割愛します。
実行
今回は業務上引き継いだおよそ4年もののプロジェクトにて検証をかけます。 ただし会社のコードはさらせないので、エラー、キャプチャ等のサンプルは比較的リアルな再現と思ってください(笑)
./xcprojectlint --report error --validations all --project awesome.xcodeproj
結果
初回実行で 219項目 もの指摘をされました…これは心が折れます\(^o^)/
検査対象である xcodeproj
の中身はそもそもテキストエディタではあまり扱わない場所なため、解決には骨が折れました…(^_^;)
問題を分類するため、以下のような手順に切り替えました。
対応
チェックの際、 オプションを刻む実行 に切り替えました。
xcprojectlint
は5つ内容をチェックしてくれます。
初回実行では --validations all
で実行してしまったのですべての検証が行われました。
以下の順序に切り替えます。
1. empty-groups
空のグループを検出してくれます。こちらも不要なものは削除していきます。 一番わかり易いのでこちらから対応しました。
error: Xcode folder “awesome/samples” has no children.
2. items-in-alpha-order
ファイルの並び順がフォルダ・ファイルのアルファベット順であることをチェックします。
error: Xcode folder “awesome/controllers” has out-of-order children. Expected: ["comment", "friend", "game", "menu", "shared"] Actual: ["shared", "comment", "menu", "game", "friend"]
Expected があるべき並び方となっていますが、Xcodeのソートを利用するとフォルダ・ファイルを区別せずに名前順になります。ここは若干手作業が必要になりました。
3. files-exist-on-disk
実ファイルが存在しないものを教えてくれます。ナビゲータ上でレファレンスが赤字になっている箇所ですね。こちらはリファレンスを消していくことで解消します。
New type found: ["versionGroupType": wrapper.xcdatamodel, "path": awesome.xcdatamodeld, "isa": XCVersionGroup, "sourceTree": <group>, "children": <__NSArrayM 0x1234567890A>( 1234567890ASDFGHJKLQWER ) , "currentVersion": 1234567890ASDFGHJKLQWER]
イニシャルコミットで作られたものの、利用されずにファイルだけ消されたような形跡がいくつかありました。
4. disk-layout-matches-project
実ファイルの所在とナビゲータの配置がマッチしているか確認してくれます。 先頭にどのファイル名、フォルダ名が表示されますが、パスは表示されないのでこちらも少し頑張って検索しながら調整していく感じです(^_^;)
error: File “TopViewController.m” (1234567890ASDFGHJKLQWER) is misplaced on disk, or wrong kind of reference. error: Folder “items” (1234567890ASDFGHJKLQWER) is misplaced on disk, or wrong kind of reference.
また、Xcodeのフォルダとグループは似て非なるもので、内包する実体との関係が少し変わってくるようです。グループが正しく設定されていない箇所を指摘されます。
グループについてはLocationにて相対グループに統一し、フォルダアイコンから実ファイルの相対パスを設定することで、ナビゲータ上のファイル移動に実ファイルも対応されるようになりました。
5. build-settings-externalized
こちらが最後で最難関でした。
ビルド設定は project.pbxproj
ではなく、個別ファイル(xcconfig
)で管理されるのが望ましいようですが、こちらはまだ徹底できていません。
/Users/ttaniguchi/work/awesome/awesome.xcodeproj/project.pbxproj:2134: error: Pods-awesome.development.xcconfig (development) has settings defined in the project file.
なんとか5ステップを通して、8〜9割がたはLinterを通すことができました。 作業を通してナビゲータの整頓方法や、グループ、ファイルの差異、プロジェクト設定関連のファイルレイアウトを理解することができました。
Linter はこのあたりを読み解くきっかけとしても実行してみてよかったです。
iOS開発の事始め
今まで近くて遠い存在だったiOS開発ですが、ひょんな事から先月より自社アプリの主担当に就任し、突貫で技術習得しました。 「ピンチはチャンス」 、この1ヶ月は会社の理解もあり引き継ぎ名目で集中してインプットができました。
ここで1ヶ月を振り返り、覚えたことをメモがてら記録しておこうと思います。
やったこと
Xcodeの使い方を学ぶ
ウィンドウ名称の把握
まずは各ウィンドウの名称を把握し、ググれる準備からです(^_^;)
【アプリ開発】Xcodeのウィンドウ名称 | Fussan Blog
こちらのサイトなど、参考にさせていただきました。 また、書籍でいくつかのXcodeバージョンのキャプチャなども確認しました。
ファイルタイプの把握
利用されているファイルの種類についても少しまとめました。
- .xcodeproject: Xcodeプロジェクト。実体はディレクトリで存在する。
- .xcworkspace: Xcodeワークスペース。Pods利用など、プロジェクトが複数になるときに利用。
- .plist: プロパティリスト。内部的にはxmlで記載される、おもに設定ファイル。
- .h: Objective-Cヘッダーファイル。
- .m: Objective-Cメインファイル。今回の主戦場。
- .swift: Swiftファイル。残念ながら当該のプロジェクトではほぼ取扱なし…
- .xib: XML Interface Builderファイル。単ページのテンプレートフォーマット。
- .storyboad: Storyboadファイル。画面遷移を可視化できる新テンプレートフォーマット。
- xibからstoryboadへの完全移行も共存も可能。
- .xcassets: アセットカタログ。ディレクトリ構造のファイル群を
contents.json
を用いてカタログ管理している。
エディタの把握
Xcodeを使った最初の違和感は、ツールを触った際に出てくる git差分 でした。どの操作がどのコードに影響を与えているのかが、序盤の肝となりました。
ナビゲータ/プロジェクトエディター
ナビゲータの ファイルツリーは実ファイルの配置と異なります 。こちらは [プロジェクト名].xcodeproj
下の project.pbxproj
で管理されており、ファイルの並び順が変わった際にもコードが書き換えられます。
ナビゲータツリーのルートをクリックすると、プロジェクトやターゲットの設定(下図)が確認できますが、こちらも [プロジェクト名].xcodeproj
下のxml等に対する書き出しを行っています。
なので、意図する書き換え以外で [プロジェクト名].xcodeproj
下に差分が出た際はマウス操作等による可能性もあり、ちょくちょくコミットから外しています。
アプリ起点について
コードリーディングに際して真っ先に気にする起点についてもこちらに設定がありました。Main Interface を用いて起点となる Storyboard
が選べるようです。
とはいえ、 AppDelegate.m
も起動時に実行されるので、こちらでインスタンス生成しても良さそうです。
インターフェイスビルダー/ストーリーボード
xib/storyboard を開いた際はこれらのエディタが起動しています。こちらもXcodeのバージョンアップでオプションの追加などが発生し、ときおり意図せずコードが勝手に書き換わるケースがあります。
アセットカタログ
xcassets は実ファイルが json
で存在するのですが、画像をサイズで括って管理するのに便利です。旧仕様だとおそらくファイル名に hoge@2x.png
などと節尾句を設けるのがセオリーだったようですが、こちらのほうが一覧性もあるので、追々完全移行する予定です。
唯一、多言語対応の考慮がされていないのが難ありです。
Objective-Cを学ぶ
ネット上の記事やブログはSwiftに席巻されていて、Objective-Cについてはあまり残っていませんでした。こちらは書籍を購入し体系的に学習中です。
- 作者: 荻原剛志
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2011/12/23
- メディア: 単行本
- 購入: 14人 クリック: 98回
- この商品を含むブログ (25件) を見る
NSLog(@"test");
最初に学ぶべきはどの言語でもダンプでしょう。わたしはそのほうが捗ります。
- コード実行箇所のあたりを付けて、ブレイクポイントで確認。
- ダンプで細かな値なども確認。
これで実動を踏まえたコードリーディングが可能です。 ひとまずObjective-Cはこれを利用して読み解いていく予定です。
ライブラリ管理を学ぶ
CocoaPodsの把握
iOS開発ではCocoaPodsというパッケージ管理ツールを用いるようです。
こちらを扱い始めると、実プロジェクトと別に Pods
プロジェクトが併設されます。それによって、Xcode起動直後に開くファイルが xcodeproject
から xcworkspace
に変わります。
xcodeproject
を開いてビルドしようとすると、 Libraryが見つからない という内容のエラーに苦しみます…(苦しんだ)
インプットが多く纏めきれませんでしたが、俯瞰的にこんな感じで情報収集をしていました。次はもう少し絞り込んで、メモを残そうと思います。
getUserMedia() でカメラ・マイクのブロックを個々に検知
最近詰まったので、メモっておくことにします。
ブロックによるエラーの特徴
ブラウザから getUserMedia()
を用いてカメラやマイクにアクセスすると、それらのデバイスへのアクセス許可が必要になります。これがブロック状態であった時に NotAllowedError
が飛んで来ます。
ただし、カメラ・マイクともにアクセスを求めた際、どちらかが利用できる状況であればブロックエラーが取得できません。
navigator.mediaDevices.getUserMedia({ audio: true, video: true }) .then((stream) => { this.setState({ stream }); .catch(err => console.log(err)); // カメラ・マイクともにブロックの場合のみ NotAllowedError を受け取る
上記のブロックを受けた場合は音声のみの動画、または音声のない動画が取得出来ます。これはこれで、プライバシーを尊重したブロックの結果なのですが、開発都合で個々のブロックをキャッチしたいケースが多々あると思います。
対応策
以下のコードが対応策を施したものです。
stream を取得したい getUserMedia
を実行した後に、 マイクのみ、カメラのみの getUserMedia
を実行することで、こちらが NotAllowedError
エラーを取得してくれます。
navigator.mediaDevices.getUserMedia({ audio: true, video: true }) .then((stream) => { this.setState({ stream }); // マイク単体検証(ブロック有無) navigator.mediaDevices.getUserMedia({ audio: true }) .then(streamTmp => streamTmp.stop()) .catch(err => console.log(err)); // カメラ単体検証(ブロック有無) navigator.mediaDevices.getUserMedia({ video: true }) .then(streamTmp => streamTmp.stop()) .catch(err => console.log(err)); }) .catch(err => console.log(err));
getUserMediaを連投して大丈夫かな、という懸念はありましたが、Android数端末、Windows等で確認したところ問題は見られませんでした。
ただ個別チェックに利用した stream は取得後すぐに止めています。( streamTmp.stop()
)
所感
急場しのぎではありましたが、比較的シンプルに対処ができてよかったです。 それでも、これより良い解決方法などありましたらご享受いただければ幸いです。コメントなどください。
2017年を振り返る
自身の来年やるべきことを模索するためにメモを残しています。
所感
昨年にクライアントサイドに転向し、主にブラウザ対応に重きをおく開発をおこなっていました。サーバーサイドでもRailsなど新しい経験もしましたが、Javascriptの世界は作法も大きく異なり、エンジニアリングの世界が格段に広がりました。
やったこと
Reactjs
クライアントサイドの学習基盤としてReactjs+Reduxに触れられたのは非常に良かったです。APIを通してデータを取得するフローや、特に非同期の考え方はクライアントの動きを深く知ることができました。 コンポーネントのライフサイクルはネイティブにも通じる考え方で、今後はiOSやAndroidの開発にも触れてみたいと思っています。
Ruby / Rails
API開発とRSpecコーディングに触れる機会は多かったです。bundleもトラブルが多かったので、そこそこ多く調べましたね…特にVagrantではnfsストレージ上でbundleがうまく動かないトラブルもありました。CコンパイルがMacローカルのコアを認識しつつVagrant内CentOSで動くみたいな(^_^;) kaminariがCで書かれているのも知って驚きました。
CSS
Animationやレイアウトについて、実作業ベースで苦しみました(笑) 特にレイアウトについては縦方向でのセンタリングの難しさや、ブラウザによって出る描画差異なども実践なくしてはわからないものが多かったです。 flexやjustify-contentなどの魔法の単語を知って作業がかなり楽になりました。translateとtop、bottomを組み合わせて縦位置をど真ん中に合わせるなども今は重宝しています。(これはいずれブログにまとめたい…)
WebRTC
ブラウザができることが大きく広がっていることを知りました。 以下のコード、htmlにて保存してChromeで開いてみてください。カメラが起動します(笑)
<html> <body> <video id="video" width="640" /> </body> <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script> <script> navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720 } }, (stream) => { const video = document.querySelector('#video'); video.src = URL.createObjectURL(stream); video.onloadedmetadata = (e => video.play()); }, err => console.log("The following error occurred: " + err.name), ); </script> </html>
ローカルHTMLでもカメラがいとも簡単に起動する、それを保存したりもできる、ネイティブアプリとブラウザとの違いはどんどん少なくなっているようです。
逆に言えば、Webエンジニアに求められることもどんどん増えているわけで、今後も精進が必要そうです(^_^;)
Xcode
業務都合で自社アプリのビルド程度まではおこなうようになりました。開発はまだ触れていませんが、エラーコンソールとBuild Settingくらいは読むようにはなっていました。ビルドを行うようになって意識が変わったことのひとつに、MacOSとXcodeのバージョンは比較的早く最新のものを追うようになりました。
モヒカンSlack
kotakanbeさんが運用されているSlackチームですが、こちらの利用で情報収集の効率が格段に良くなりました。 qiita.com
冬眠気味だったTwitterアカウントも改めて情報収集に活かせるようフォローを増やしたり手をかけましたが、情報収集方法も年々進化していますね。
TILをやってみたが…
Today I learndでTILですね。1週間も持ちませんでしたが(^_^;)
ブログよりも細かい粒度で身につけたことを残したいと思いはじめましたが、情報が少なすぎると一生懸命ネタを増やそうとしてしまうのがブログやってるときの癖で… 調べたことを一個単位で残していくのは非常に効率的だと思うので、今後はもう少しマメに書いていきたいです!
GitHub - ttaniguchi/til: Today I learned
まとめ
今年はわたしにとってはクライアント元年であり、非常に楽しい試みを多く経験できた年だったと思います。ただ、環境的には同じ技術軸で作業をする人間が身近におらず、ガラパゴス懸念を感じながらLintだ勉強会だと他者の技術や標準化にやや枯渇した時期でした。 来年は身近なメンバーに技術普及をすることで切磋琢磨できる環境をつくることにも尽力したいですね。
それと、やはりネイティブには触れていきたいです。Reactjsかvuejsか、みたいな時期もありました。それでもReactjsを選んだのは「アプリも作れるみたいだし…」というとろこもあったわけで。 そこに回帰して、来年はプライベートでReact Nativeをはじめてみようかと思っています。(1年くらい前にHwllo Worldくらいまではやった気がします)
今年も残すところ僅かですが、良いお年を! Happy Hacking!
Github二段階認証後はID + tokenを使う
https://github.com/settings/security
困ったこと
会社のルールでGithubで二段階認証(SMS)をおこなっていたのですが、コンソールでID+パスワードを求められた際に認証不足で処理が通らなくなります。
こんな場合です。
$ git clone https://github.com/ttaniguchi/private-repository.git Cloning into 'private-repository'... Username for 'https://github.com': ttaniguchi Password for 'https://ttaniguchi@github.com':
対処方法
パスワードの代わりにPersonal access tokensを作れば大丈夫でした!
https://github.com/settings/tokens
これを知らないと二段階認証への移行に結構足踏みしそう… メモがてら共有します。