- 投稿日:2020-07-29T21:43:06+09:00
[swift5]Protocolの作成方法
実装のポイント
Protocolの作成方法を5つの項目に分けて言語化及び要約してアウトプットしていきます。
初学者の方(私も初学者ですがw)はProtocolに関してわからない部分が多いと思いますが、実装の流れを掴む事ができればコードは書ける(Xcodeのおかげw)と思いますので実装の流れに注目して下さい!今回は
ViewController
とNextViewController
の2画面が存在し、
NextViewControllerからViewControllerへメソッドを委任したいと思います。環境
swift5
Xcode 11①Protocolの作成
まず
nextViewController
で下記コードのようにProtocolの定義と、Protocolで使用するメソッドの宣言を行います。今は使用するメソッドの規則だけでOKです。NextViewController.swiftprotocol プロトコル名ProtocolDelegate { //規則のみ決める func メソッド名(委任したい値: 型) } //プロトコルを変数に代入して宣言(? = nil NG) var 変数名: プロトコル名ProtocolDelegate?②他クラスで発動(戻るボタンpushで発動の場合)
今回は戻るボタンpushで発動する場合のコードを記述します。
NextViewController.swift@IBAction func backButton(_ sender: Any) { //delegateメソッドを任せたクラスで発動 ①で宣言した変数名.メソッド名( 委任したい値: 値(変数名) ) //ボタンを押して戻る処理 dismiss(animated: true, completion: nil) }③使用(委任)するクラスにProtocolで宣言
ViewController
のclass宣言箇所に①で宣言したプロトコル名ProtocolDlegate
を記述。するとエラーが発生するので'Fix'を選択してXcodeの補完に従い、④のようにメソッドを作成する。
ViewController.swiftclass ViewController: UIViewController,プロトコル名ProtocolDelegate { }④Protocolで書かれたメソッドを記述
③で自動補完されるメソッド。
ViewController.swiftfunc ①で宣言した規則のメソッド名(委任したい値: 型) { }⑤NextViewControllerからViewControllerへ値を受け取る場合
ViewController.swiftoverride func prepare(for segue: UIStoryboardSegue, sender: Any?) { //変数nextVCに委任したい側のコントローラー名を代入し値を渡す let nextVC = segue.destination as! NextViewController //委任完了コード nextVC.delegate = self }最後に
もし誤っている箇所や疑問がある場合はコメント欄にて受け付けておりますのでご連絡お待ちしております。是非参考にしてください!
- 投稿日:2020-07-29T19:22:18+09:00
Xcode 11でビルドしたアプリをiOS 14 betaシミュレータ上で動かす方法
最初の1分ほどの手順で、それ以降はXcode 11からiOS 14 betaシミュレータを直接選び、アプリ(iOS 13 SDK)を実行することが可能になります。
何か問題や気付いたことがありましたらコメントで教えていただけると助かります。
準備
- macOS Catalina 10.15.6
- Xcode 12 beta 3
- Xcode 11.5
More Downloads for Apple Developers
このApple公式ダウンロードサイトからXcode 12 betaとXcode 11のxipファイルをダウンロードしてインストールしています。
ビルドを行うXcodeバージョンは11.5でなくてもOKです(Xcode 11.6が現時点で最新)。
App Store版のXcodeでは試していないため有効かわかりません。xipファイルから解凍した各Xcodeは以下の通りに配置しリネームしてあります。
* Xcode 12 beta 3: /Applications/Xcode12-beta3.app
* Xcode 11.5: /Applications/Xcode.app各Xcodeの初回起動時に
Command Line Tools
をインストールするダイアログが表示されるので、各Xcodeのバージョンに対応するCommand Line Tools
をインストールしておいてください。手順
1. Xcode 12 betaを起動
Command Line Tools
のバージョンを指定します。sudo xcode-select -s /Applications/Xcode12-beta3.app(別法でメニューから指定することもできます Preference > Locations > Command Line Tools)
2. beta版シミュレータアプリを起動
新規プロジェクトでも何でもいいので、iOSアプリを実行しbeta版シミュレータアプリを起動します。
3. Xcode 12 betaを終了
このとき、beta版シミュレータアプリは起動させておきます。
4. Xcode 11を起動
Command Line Toolsのバージョンを指定します。
sudo xcode-select -s /Applications/Xcode.appこれで先程起動させたbeta版シミュレータが、より古いバージョンのXcodeから選択&実行できるようになりました
既存のプロジェクトでは以下の画像のようになります。
別法
Test iOS Build from Production Xcode on Beta iOS Simulators
別の方法として、Xcode 11でビルドしてiOS 13のシミュレータ上にあるアプリの保存場所をActivity Monitorアプリで特定。それをドラッグ・アンド・ドロップでiOS 14 betaのシミュレータの画面上に移すという方法が紹介されていました。これは少し面倒くさいですね。
- 投稿日:2020-07-29T13:32:48+09:00
AutoLayoutで使えそうなUIViewのConstraintsExtension
Contraint用Extensionがおすすめ
コードベースで書いた経験が少なかったため、Constraintをどうするか調べていたところ、とても参考になる記事がありました。
一部自分で手を加えましたが、とても使い勝手が良いです。extension UIView{ func anchor(top: NSLayoutYAxisAnchor? = nil, left: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, right: NSLayoutXAxisAnchor? = nil, paddingTop: CGFloat = 0, paddingLeft: CGFloat = 0, paddingBottom: CGFloat = 0, paddingRight: CGFloat = 0, width: CGFloat? = nil, height: CGFloat? = nil) { translatesAutoresizingMaskIntoConstraints = false if let top = top { topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true } if let left = left { leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true } if let bottom = bottom { bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true } if let right = right { rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true } if let width = width { widthAnchor.constraint(equalToConstant: width).isActive = true } if let height = height{ heightAnchor.constraint(equalToConstant: height).isActive = true } } func center(inView view: UIView, yConstant: CGFloat? = 0) { translatesAutoresizingMaskIntoConstraints = false centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: yConstant!).isActive = true } func centerX(inView view: UIView, topAnchor: NSLayoutYAxisAnchor? = nil, paddingTop: CGFloat? = 0) { translatesAutoresizingMaskIntoConstraints = false centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true if let topAnchor = topAnchor { self.topAnchor.constraint(equalTo: topAnchor, constant: paddingTop!).isActive = true } } func centerY(inView view: UIView, leftAnchor: NSLayoutXAxisAnchor? = nil, paddingleft: CGFloat? = nil, constant: CGFloat? = 0) { centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: constant!).isActive = true if let leftAnchor = leftAnchor, let padding = paddingleft { self.leftAnchor.constraint(equalTo: leftAnchor, constant: padding).isActive = true } } func setDimensions(width: CGFloat, height: CGFloat) { translatesAutoresizingMaskIntoConstraints = false widthAnchor.constraint(equalToConstant: width).isActive = true heightAnchor.constraint(equalToConstant: height).isActive = true } func addConstraintsToFillView(_ view: UIView) { translatesAutoresizingMaskIntoConstraints = false anchor(top: topAnchor, left: view.leftAnchor, bottom: bottomAnchor, right: view.rightAnchor) } }参考記事
https://medium.com/@suj9763/auto-layout-extension-in-swift-programmatically-fe1e7cca13e5
- 投稿日:2020-07-29T12:23:16+09:00
【個人開発】FlutterとFirebaseでサボり防止アプリを作った
先日、個人開発アプリをリリースしました!やったね!!!
審査も通りまして、現在App StoreとPlay Storeで配信されております。
せっかくなので、利用した技術のメリットと注意点をまとめておこうと思います。
作ったアプリ
これです。
広報用ページも作ってみたのでリンクを貼っておきます。
広報用ページはスマホで見る用にレイアウトしてます。
英語名: Procrastinators Watch Mutually
解決したい課題
やらなきゃいけないことがあるのに、なかなか取り組めずにグダグダしてしまう経験がみなさんあると思います。
でも、会社や学校で「今はこれをやる時間です」と管理されたり、誰かと一緒に「今からやるぞ!」って決めると、取り組めますよね。
そういう「誰かと一緒」「時間を管理される」という状況をアプリ上で再現して、作業に取り組みやすくするためのアプリです。
解決方法
- 一緒に作業してるメンバーと作業内容が表示される
- タイマーで全員同時に作業時間と休憩時間を指定される(49分作業12分休憩)
- ちゃんと取り組めたかどうか自己申告し、それに対して褒めたり罰したりできる
- 褒められたいし、自分に嘘をつきたくないので、作業に取り組むモチベーションアップ
- 罰された人は社会貢献活動で償うまでアプリを利用できない
- 社会貢献活動とは動画広告視聴のことで、広告主・広告配信業者・アプリ制作者に貢献できる
- サボりに対し、有意義な軽い「罰」を用意することで、作業に取り組むモチベーションアップ
そんなアプリです。
ということは、広告の実装が必要ですね。
また、ユーザーの入力した内容が他者から見えるので、プライバシーポリシーや利用規約で不適切な入力を防止し、違反者にはミュートやBANをできるようにする必要があります。
そのためにはログイン機能でユーザーを識別する必要もありそうですね。
では技術方面を見ていきましょう。
Flutter
フロントエンドはFlutterを使います。
Flutterのメリット
最大のメリットはなんと言っても、AndroidとiOSの両アプリをそれぞれ作らなくて済むことです。
また、同じメリットを持つフレームワークは他にもありますが、Flutterが今最も勢いがあるフレームワークと言えると思います。コミュニティも活発で情報が得やすいです。
あのGoogleがかなり力を入れて作っているという安心感もありますね。
今後はWebや、Mac、Windows用のネイティブアプリも作れるようになるということで、スマホアプリに限らず広範囲にわたるクロスプラットフォーム開発が可能になっていくようです。
Webは2020年7月27日現在、既にかなりのレベルでアプリが作れます。
開発環境
Flutterの開発環境はAndroid Studioを使いました。
VSCodeでもいいと思います。
Flutter Inspectorの見やすさや新規プロジェクトの作りやすさでAndroid Studioを選びましたが、それも半年以上前のことなので、今のVSCodeと比較するとどうかわかりません。
静的解析
Flutter開発をする際は静的解析を有効にするようにしましょう。
これはほぼ必須だと思います。
行儀がよく見やすい、ルールの統一されたコードを書くことが出来ます。
詳しくはこちら。
https://dart.dev/guides/language/effective-dart
https://medium.com/flutter-jp/analysis-b8dbb19d3978
状態管理手法
Provider + ChangeNotifier パターンを採用しました。
2020年7月27日現在、Flutter公式が最もおすすめしている方法です。
Flutter開発を始めると状態管理手法に悩むことになると思いますが、まずはこれでいいと思います。
他の方法については、こちらの記事を参考にしてもらえると嬉しいです。
Flutterの状態管理いろいろ比較 〜グローバル変数StateからBLoCパターンまで〜
なお、リンク先記事を書いた後で登場した
- StateNotifier
- Riverpod
- Cubit
などの方法については記事内で触れていません。興味ある方はお調べください。
筆者自身の次のアプリはRiverpod+ChangeNotifierパターンで作ろうと思っています。
多言語対応
英語・日本語・中国語の3言語に対応させました。
多言語対応の方法はこちらの公式解説のAn alternative class for the app’s localized resourcesを参考にしつつ、オレオレ手法でやってます。
公式オススメの方法は、自動コード生成を含んでおり、それと静的解析ツールがバッティングして警告を吐きまくり、静的解析の例外設定をしてみたらそこにバグがあり例外設定が効かず…というトラブルに見舞われたので、それ以来オレオレでやってます。今はどうなんでしょう。
筆者のオレオレ手法は、自動コード生成がなく、コード補完も効いて
L10n.of(context).title
のように欲しい文言を得られるので、悪くないと思ってます。ここでは詳しく解説しませんが、そのうち記事にするかもしれません。
なお、もちろん、後述のプライバシーポリシーやスクリーンショット、ストア上のタイトルや説明文も全て3言語分用意してます。ちょっと大変。
Firebase
バックエンドにはFirebaseを使っています。
ログイン・データベース・サーバーサイドロジック・広告・プライバシーポリシーページの用意を全てFirebaseに頼っています。様様ですね。
下記に出てくるfirebase関係のパッケージを使うにはfirebase_coreパッケージが必要になるのでご注意ください。
Authentication
Google、Facebookアカウントを使ったログインを実装しました。
firebase_authパッケージを使います。
ただし、iOSアプリの場合はサードパーティログインにAppleを加えることが必須なので、iOS版に限りAppleログインも実装しました。
Appleに関してはこちらの記事が大変参考になりました。
[Flutter] Sign in with Apple を Cloud Functions 無しで実装する
Androidアプリの方は、Androidのapkファイルの署名に使った証明書のハッシュをFirebaseやFacebookに伝えておく必要があるのでご注意ください。
デバッグ時にデバッグ用証明書のハッシュを渡していても、リリース時にはリリースに使った鍵の証明書のハッシュを伝える必要があります。筆者はこれを忘れていて、リリース直後にAndroid版で一切ログインできない事故を起こしました。
Firestore
cloud_firestoreパッケージを使います。
Firestoreの使い方・考え方についてはこちらの動画シリーズがとてもわかりやすいので一通り見ておくといいと思います。
従来のRDBMSとは結構異なる考え方が推奨されてます。
「データの正規化を頑張るより、重複を許した方が良い」とか「リアルタイム接続をデフォルトにして一件ずつフェッチするのを例外的な場合に限定しよう」とか。
「クエリ一回でも、読み込んだドキュメントの件数に応じて料金がかかる」なんかは結構重要です。
セキュリティルールとテスト
Firestoreで重要になるのがセキュリティルールです。
アクセス権限の管理だけではなく、サーバーサイドバリデーションもセキュリティルールを使って行います。
筆者はセキュリティルールとそのテストはAndroid StudioではなくVSCodeで書いています。
テストコードをTypeScriptで書いているのですが、Android Studioではシンタックスハイライトや補完が効かないので。
セキュリティルールだけ書いていくとゴチャゴチャしてきて管理が大変なので、やはりテストとセットで書いていくのが良いと思います。
その際はこちらの記事を参考にしてもらえたらとても嬉しいです。
VSCodeデバッガを使ってCloud FunctionsとFirestoreの連携テスト(TypeScript)
2020年6月のバージョンで、セキュリティルール内で一時変数が使えるようになったりして、どんどん便利になっていますね。
New improvements to Firestore Security Rules
Functions
Firestoreの中身をどうしてもサーバーサイドから操作したい時は、Cloud Functionsを使います。
「どうしても」と書いたのは、Firestoreの操作をする時はまず第一にクライアントのSDKから操作することを考えるべきだからです。
Firestore SDKはオフラインサポートなどいろいろうまいことやってくれるので、積極的に利用しましょう。
先程の動画シリーズの一つですが、これが参考になります。
https://www.youtube.com/watch?v=oDvdAFP6OhQ
また、Functionsを使う必然性がある場合でも、呼び出し可能関数を作るのはできるだけ避けましょう。
理由はこちらの記事が参考になります。
CQRSを学ぶついでにCloud FunctionsとFirestoreを連動させる時の小技も学ぶ
Web APIの操作に慣れているとつい同様にAPIを作って叩きたくなりますが、耐えましょう。クライアントからの操作で完結するものは完結させます。
じゃあどうするかというと、Cloud Functionsには、さまざまな「トリガー」が用意されています。
- Firebase Analyticsに新しいイベントが送られた時
- Firebase Authentication で新しいユーザーが作られた時
- Firestore上でドキュメントが削除されたとき
などなど、たくさんあります。
これらに応答してFunctionsが起動するようにしましょう。
ただし、Functions上の各関数は一回のトリガーに対して複数回起動することがあるので、「冪等」にしておくといいです。「冪等」というのは、「2回以上実行しても結果が変わらない」ということです。
今回のアプリでは、ユーザーがきちんと退室せずに放置した場合に退室処理を走らせるためにFunctionsを利用しています。
hosting
サーバー上にファイルを置いておき、特定のURLでアクセスできるようになります。
一昔前だったらレンタルサーバーを有料で借りないとこういうことはできませんでしたが、便利な時代になりました。
今回は、プライバシーポリシーを掲載したページや、広報用ページを置くために利用しています。
開発環境
FunctionsもVSCodeで書いています。TypeScriptで書いているのですが、Android Studioだと補完やシンタックスハイライトが効かないからです。
Functionsのテスト
公式記事が大いに参考になります。
また、こちらは上に既に貼ったのと同じ私の記事ですが、再掲します。参考にしてもらえると嬉しいです。
VSCodeデバッガを使ってCloud FunctionsとFirestoreの連携テスト(TypeScript)
AdMob
このアプリは広告が出るので、firebase_admobパッケージを使って広告を出しています。
ただ、このパッケージは何かと使いにくいので、色々注意が必要です。
筆者がこのパッケージについてあれこれ嘆いている様子がわかるツイッター検索結果がこちらです。
ストア申請のために
アプリが動くようになったら、ストアで配信したいですよね。
ここでもいろいろ障壁があります。
ミュート機能・通報機能
このアプリはユーザーが入力した表示名やタスク内容が他人から見えるため、「ユーザー生成コンテンツ」に該当すると思われます。
この場合、少なくともApp Storeに掲載されるためには、不適切な内容を投稿するユーザーに対して対策を施しておく必要があります。Play Storeについては未調査ですが、おそらく同様だと思います。
具体的には、ユーザーをミュートや報告する機能が必要です。
詳しくはApple公式のこちらが参考になります。
App Store Reviewガイドライン - 1.2 ユーザー生成コンテンツ
プライバシーポリシー
個人情報をどう扱うか、というものです。
すべてのアプリで必須のはずです。一切情報収集しない場合でもその旨を記述したプライバシーポリシーが必要だと思われます。
Firebase Analyticsを使っている場合は情報収集していることになるので、その旨の記述が必要ですね。
AdMobを使っている場合はユーザーに合わせた広告を出すために情報収集してますので、それについても記述が必要です。
詳しくはこちらを御覧ください。
App Store Reviewガイドライン - 5.法的事項
とはいえプライバシーポリシーなんてどう書いたら良いかよくわからないものです。
検索すると書き方の解説や雛形がヒットしますので、参考にするといいと思います。
申請用スクショ撮影
ストアで申請するためにはアプリのスクリーンショットが必須です。
これが案外面倒です。スクショとして欲しい画面が、アプリを実際に操作して簡単に作れるとは限らないからです。
それが複数端末分必要になります。
また、多言語対応している場合はその数だけ必要になります。
4画面*4端末*3言語とすると48枚必要になりますね。手動で撮っては結構な手間です。
これについては私のこちらの記事を参考にしてもらえると嬉しいです。
Flutterアプリのスクショを(極力)自動で撮る on AndroidStudio
署名について
署名周りも、アプリ配信時の結構なハードルになると思います。
これも自分の記事で恐縮ですが、概要をまとめておりますので参考にしてもらえたら嬉しいです。
Android・iOSアプリを配信する時の署名について整理する
終わりに
技術周りをまとめておこうと思って書いてみたら、自分の過去記事へのリンクが多くなってしまいました。
まあ、難所を突破するたびにその結果を記事にまとめるようにしていたので、それらへのリンクが多くなるのは必然か……。。。。
ということで、皆様、アプリ開発ライフを楽しみましょう!
サボり防止アプリもよろしくおねがいします!これで時間管理しながらアプリ開発してくれたらメチャクチャ嬉しいです!
- 投稿日:2020-07-29T09:21:41+09:00
Fastlaneを使って、Firebase App Distributionを自動化する
Fabric終了に伴い、Firebase App Distributionを用いてアプリを配布しているプロジェクトは数多くあると思います。
手動で配布することもできるのですが、その場合、
1. ipaファイル作成
2. Firebaseコンソールに移動
3. ファイルのアップロード
4. テスターの指定
などと毎回同じ作業をするのは面倒です。そこで個人プロジェクトでこちらの作業をfastlaneコマンド一発でできるようにしたので、その時の手順を記します。
今回解説するのは
- fastlaneのセットアップ
- fastlaneによるipa作成、アップロード方法
です。Installing fastlane
まずはHomebrew経由でfastlaneをインストール
brew install fastlaneプロジェクトのルートディレクトリで下記コマンドを実行。
fastfileが作成され、こちらに後ほど配布するためのコードを記述します。fastlane initプラグインを追加
fastlane add_plugin firebase_app_distributionローカルマシンでFirebaseにログインできるようにする
ドキュメントに従います
Firebase CLIをダウンロード
curl -sL https://firebase.tools | bash以下コマンドで確認
firebase loginfirebase-toolsのインストール
まずはNode.jsをダウンロードします。
https://nodejs.org/ja/download/プロジェクトのルートディレクトリで以下コマンドを入力。package.jsonが作成されます。
npm initこれでfirebase-toolsをインストールすることができます。
npm install firebase-tools以下のパスはgitignoreに追記。
node_modules/fastfileへの記述
platform :ios do desc "deploy DEV on Firebase App Distribution" lane :distribution do # .ipaファイルの作成 gym( workspace: "hoge.xcworkspace", scheme: "hoge", export_method: "ad-hoc", export_options: { method: 'ad-hoc', teamID: 'hoge', provisioningProfiles: { 'bundle identifier name' => 'provisioning profile name' } } ) # firebase app distributionに.ipaアップロード firebase_app_distribution( app: "1:1234567890:ios:0a1b2c3d4e5f67890", testers: "emailadress@gmail.com, emailadress2@gmail.com", release_notes: "hoge", firebase_cli_path: "node_modules/.bin/firebase" ) end endfirebase_app_distributionについて
appの引数にはFirebaseのプロジェクト設定画面にあるアプリIDを指定。(プロジェクトIDじゃないよ)
Provisioning Profileの作成
Dev環境かつAutoでやってたので、appleのdeveloperサイトから手動で作成する必要があった。
Dev環境用のProvisioning Profileを作成し、その名前をFastfileに記述。
ダウンロードしたら、起動して、キーチェーンに登録までする。実行
fastlane distribution
で実行できます。
実行したら、Firebaseコンソール -> プロジェクト -> App Distributionで新たなバイナリーができているかを確認しましょう。参考
https://firebase.google.com/docs/app-distribution/ios/distribute-fastlane?hl=ja
https://qiita.com/fuwamaki/items/a9745e1242e24430eb4c#fastlane%E3%82%92%E7%94%A8%E3%81%84%E3%81%9Ffirebase-app-distribution%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E6%96%B9%E6%B3%95
- 投稿日:2020-07-29T09:08:14+09:00
Codemagic でモバイルアプリの CI/CD を始めましょう
この記事は、Codemagic の運営元である Nevercode Ltd の依頼で作成しました。2020/7/6 に公開された オリジナルの英語記事の日本語訳に加え、冒頭に私のコメントを、末尾におすすめの Codemagic 関連の日本語記事へのリンクを列挙しています。
Codomagic は、今年の2月に発表された Flutter UX 調査チームによる Q4 2019 の調査結果において、開発者が CI/CD で採用しているサービスのトップ3に挙げられており、(Codemagic、 Github Actions、 GitLab)、その中でも満足度が最も高かったことが示されています。
Codomagic は、Google と提携して Flutter 専門の CI/CD サービスとして開始されただけあって、Flutter を手厚くサポートしています。また、以下の翻訳で示されているように、Flutter に加えて Android ネイティブ、 iOS ネイティブ、React Native のサポートが追加されましたので、既存のそれらのアプリの資産がある場合でも、Codomagic をすべてのアプリに対応する統一した選択肢として検討できるようになりました。
また、プライベートリポジトリでもクレジットカード登録なしで使える無料枠が用意されていますので、試用を開始する敷居がとても低いです。
公式のドキュメンテーションや公式ブログの内容も、英語ではありますが、まずまず充実していると言えるのではないでしょうか。
あらたに Flutter プロジェクトを始める際の CI/CD サービスの選定作業については、Codemagic の試用から始めるのがひとつの無難な選択肢でしょう。
以下が、オリジナルの英語記事の日本語訳です。
2018 年にロンドンで開催された Flutter Live おいて、 Nevercode は Google と提携し、Flutter アプリ専用の CI/CD ソリューションとして Codemagic を立ち上げました。Codemagic を使えば、Flutter アプリを辛い設定作業をせずにテストしてリリースできます。
Codemagic は Flutter の扱いに熟達していますが、今やそれだけにとどまりません。Flutter アプリでないネイティブアプリでも同等に扱えるように、
codemagic.yaml
ファイルを使用して、ネイティブの Android と iOS アプリ、および React Native アプリの設定とビルドができるようになりました。スクリプトをより詳細に制御したい場合は、カスタムスクリプトを実行したりカスタムワークフローを作成できます。高品質なアプリをさらに迅速に開発できるようになりました。ここでは、Codemagic を使えば、Flutter アプリ、Android ネイティブ アプリ、 iOS ネイティブ アプリ、React Native アプリの CI/CD をいかに簡単に設定できるのかを、その手順を説明を通じてご紹介いたします。
必要条件
Flutter アプリ、iOS ネイティブアプリ、Android ネイティブアプリ、React Native アプリを Codemagic 上でセットアップするには、いくつかのものが必要です。
- もちろん、Flutter アプリ、iOS ネイティブアプリ、Android ネイティブアプリ、React Native アプリとそのテストコードが必要です。そして、それらのアプリは GitHub、GitLab、または Bitbucket でホストされていることを念頭に置いています。
- App Store や Play Store に公開したい場合は、証明書や Provisioning Profile のようなコード署名を用意します。
- ビルドレポートやアーティファクトを送信する場合は、Slack のワークスペースを用意します。
以上です。これでアプリに CI/CD を追加する準備ができました。では、実際に設定することを通じて、基本的なことを説明していきましょう。なお、コード署名と公開作業についてはこのチュートリアルでは対象とせず、別途説明とさせていただきます。
Codemagic にアカウント登録
最初の一歩は、codemagic.ioウェブサイトにアクセスし、GitHub、GitLab、または Bitbucket のアカウントで Codemagic のアカウント登録をすることです。これで、そのサービスのすべてのリポジトリーを Codemagic アカウントに統合して扱えるようになります。
アプリケーション ダッシュボード ( Applications Dashboard )
サインインすると、Codemagic のダッシュボードにアプリのリポジトリーの一覧が表示されます。一覧をフィルターにかけたり検索したりして、ビルドしたいアプリを見つけることができます。初回のアクセスでは、以下のように表示されるでしょう。
ビルドのワークフローを設定するには、Set up buildボタンをクリックします。
設定がすでに済んで、まだビルドを開始していない場合は、このように表示されます。
Finish build setup をクリックして設定を終え、ビルドを開始できます。
ちなみに、以前に Codemagic 上でビルドしたアプリがある場合は、以下のような表示になります。
Start new build をクリックして以前の設定でビルドを開始したり、Settings(歯車のアイコン)をクリックして変更したりできます。
ビルドの設定
Set up buildボタンをクリックすると、このページが表示されます。ここでは、プロジェクトの種類を選択できます。
この一覧から適切なもの選択するだけです。選択すると、ワークフローの設定画面に移動します。
Flutter の設定
このページでは、以下のような UI で Flutter アプリのビルドワークフローを設定できます。
ビルドワークフローをより詳細に制御したい場合は、Download configuration ボタンをクリックして
codemagic.yaml
ファイルを使用できます。この
codemagic.yaml
ファイルを使用して、ワークフローを変更できます。プロジェクトのルートディレクトリに置いて、VCS にコミットするだけです。リポジトリーにこのファイルがあれば、Codemagic が自動的に検出します。Start your first build ボタンをクリックして、Flutter アプリのビルドをすぐに開始できます。ワークフローをまだ変更していない場合は、以下の一連のステップのデフォルトのワークフローが使用されます。
ビルドマシンの準備、ソースコードのチェックアウト、Flutter の依存関係のインストール、テストの実行、アプリのビルド、アーティファクトの公開といった一連のステップがあります。これが基本的な CI/CD のワークフローに必要なものです。各ステップをクリックして展開すると、Codemagic はそれぞれのステップのログを表示します。
その他の設定
Flutter アプリ以外のプロジェクト(Android ネイティブアプリ、iOS ネイティブアプリ、React Native アプリ、または Flutter Module)をビルドする場合は、
codemagic.yaml
ファイルを使用してワークフローを設定する必要があります。選択したプロジェクトの種類ごとにテンプレートが用意されています。ビルドレポート
ビルドが終了すると、Codemagic のダッシュボードに、ビルド時間、ビルドステータス、コミットなどの概要とそれらの詳細が以下のように表示されます。
これに加えて、デフォルトでは iOS と Android アプリの両方の、ビルドのステータスとアーティファクトがメールで送信されます。メールの内容は以下のようになります。
Slack の設定をすることで、Slack チャンネルにビルドレポートを投稿させることもできます。
以上です!なにも設定しなくても Flutter アプリに CI/CD サポートを追加できました。これが Codemagic のマジックです。
ビルドの失敗
ここまでは、すべてが完璧に動作しているハッピーパスのシナリオを説明してきましたが、現実の世界では必ずしもそうなるとは限りません。ビルドに失敗したり、テストに失敗したり、調査が必要な問題が発生することもあります。Codemagic は、各段階においてそれが成功したか失敗したかに関わらず、詳細なログを提供しています。これらのログは失敗したビルドをデバッグするのに非常に便利です。以下の画面は、ユニットテストが失敗していて、ビルドの失敗のすべての詳細がログに記録されているものです。
見ての通り、インテグレーションテストとウィジェットテストは成功していますが、ユニットテストが失敗しています。これを修正することでビルドを修正できました。テストが失敗すると、それを知らせるメールもビルドログへのリンク付きで届きます。
ビルドの失敗についてもっと詳しく知るには、モバイルアプリの CI ビルドが失敗してしまう、よくある 12 個の設定間違い をお読みください。
デフォルトワークフローとカスタムワークフローの比較
デフォルトのビルドワークフローには CI/CD ワークフローに必要となる基本的なものが含まれていますが、ほとんどの場合、ビルドプロセスの一部になんらかのカスタマイズを加える必要があります。例えば、ビルドステータスを Slack や他のコミュニケーションチャンネルに送信したり、アーティファクトを Fabric や HockeyApp などの他のサービスに発行したい場合があります。これらのシナリオを実現するためには、カスタムワークフローを作成し、カスタムスクリプトを実行します。それでは、プロジェクトの必要に応じてワークフローをカスタマイズする方法を見ていきましょう。
Build フェーズ
Codemagic における Flutter アプリの Build フェーズには、ビルドプロセスを定義するためのさまざまな手段があります。どのブランチをビルドするか、そして何のイベントをきっかけにしてビルドするかを選択することから始めます。
次に、Godemagic では、以下のようなもっと詳細な設定も可能です。
- Flutter のバージョン
- アプリをビルドする設定。debug や release など
- iOS や Android、またはその両方といったプラットフォームの選択
- Xcode のバージョン
- カスタムビルドの引数
デフォルトのワークフローでは、以下の設定が選択されています。
とは言え、ビルドプロセスはデフォルトの動作をプロジェクトの必要に応じて変更することで、いつでもカスタマイズできます。Xcode の異なるバージョンや異なるリリース設定でアプリのビルドが、上記の画面のオプションの変更、さらにカスタムワークフローによって可能です。
Codemagic のもう一つの大きな特徴として、すべてのフェーズの前にカスタムスクリプトを追加できます。これにより、開発者は各フェーズの前後で任意のコマンドを実行できます。カスタムスクリプトを設定するには、単純に Build、Test、Publish などの各フェーズの上部にある
+
ボタンをクリックします。ここでは、Build フェーズの前に配置するスクリプトの例を示します。Pre-build scriptに、プロジェクト固有の依存関係のインストールなど、任意のコマンドを追加できます。
Test フェーズ
Codemagic の Test フェーズでは、開発者はテストの有効化と無効化を切り替えられます。プロジェクトで実行する Flutter テストの種類を選択できますし、テスト中に使用する追加の引数の指定もできます。プロジェクトで Flutter Driver tests を使用している場合は、使用するエミュレータの種類も指定できますし、AWS Device Farm の恩恵も受けられます。
こちらで、Flutter のテストに関する詳細をご覧いただけます。
とは言え、デフォルトの動作を無効にして、カスタマイズしたテストコマンドを使用することも可能です。例えば、コマンドラインから UI テスト(訳注: Flutter のインテグレーションテスト) だけを実行したい場合は、次のコマンドを pre-test フェーズに追加します。
flutter drive --target=test_driver/main.dartこれにより、デフォルトのテストワークフローを使用する代わりに、このコマンドが実行されます。
Publish フェーズ
Codemagic の Publish フェーズでは、ビルドレポートやアーティファクトの公開のための様々な設定が必要です。デフォルトでは、あなたが GitHub/Bitbucket/GitLab にメールアドレスを提供している場合は、メールアドレスだけが設定されています。
このフェーズでは、その他にも以下のものを明示的に設定する必要があります。
- iOS と Android の両方のコード署名に必要な情報をアップロード
- Slack の webhook を設定
- 公開のための、Google Play や App Store Connect の詳細を入力
これらに加えて、カスタムスクリプトを書いて、Fabric や HockeyApp などのサードパーティサービスにアーティファクトをデプロイすることもできます。
スクリプトの大きな力を利用して Codemagic でカスタムワークフローを設定し、アプリのビルドプロセスをより強固なものにできます。
多数のワークフロー
Codemagic では、異なる設定やバージョンのソフトウェアの要件を満たすために、多数のワークフローを作成できます。既存のワークフローを複製して名前を変更することで、新しいワークフローを作成できます。以下の手順です。
- App settingsに移動します。(訳注: https://codemagic.io/apps ページで、それぞれのプロジェクトの歯車アイコンをクリックして移動できます)
- Workflow settings セクションの、Duplicate workflow をクリックします。複製されたワークフローは、アプリ名の下の一覧に "Default Workflow (Copy)" として表示されます。ワークフローを選択し、名前を変更します。
上の画面では、デフォルトのワークフローの名前を "Custom Workflow" に変更しています。異なる Xcode のバージョンやデバッグ用設定やリリース用設定での Flutter アプリのテストなど、多くのワークフローを作成できます。
まとめ
Codemagic は、Flutter アプリ専用の公式の CI/CD ソリューションとして始まりましたが、今ではすべてのモバイルプロジェクトをこの最速の CI/CD に迎え入れています。Codemagic のマジックを使えば、設定なしで Flutter アプリのビルド、テスト、公開ができますし、カスタムワークフローを使えば環境を制御してビルドを実行できます。Android ネイティブアプリ、iOS ネイティブアプリ、React Native アプリをお持ちの場合は、
codemagic.yaml
ファイルを使用するだけで、発進の準備が完了です!ハッピー ビルディング!
お役立ちリンクと参考文献
- Codemagic の公式ドキュメンテーション
- Flutter Module をネイティブ Android アプリプロジェクトに追加して、 Codemagic でテストする方法
- Flutter Module をネイティブ iOS アプリプロジェクトに追加して、Codemagic でテストする方法
- Flutter Module が追加されたネイティブ Android アプリを、 Codemagic を使用して配布する方法
- iOS のコード署名と公開を、 codemagic.yaml を使用して行う方法
以上が翻訳です。
お役立ち日本語記事へのリンク
- 投稿日:2020-07-29T06:09:17+09:00
Xcodeシミュレーター管理コマンド
こちらが、Xcodeがローンチしたシミュレーターを管理するために実行できるコマンドです。
これらのコマンドは、あなたの端末で実行してください。この記事は、あなたが
iPhone 11 Pro Max
と名付けられたシミュレーターを実行していると仮定しています。時刻を変更する
xcrun simctl status_bar "iPhone 11 Pro Max" override --time '9:41'セルラーネットワークを変更する
Wi-Fiに切り替える
xcrun simctl status_bar "iPhone 11 Pro Max" override --dataNetwork 'wifi'Wi-Fiの信号強度を制御する
xcrun simctl status_bar "iPhone 11 Pro Max" override --wifiBars 0 xcrun simctl status_bar "iPhone 11 Pro Max" override --wifiBars 1 xcrun simctl status_bar "iPhone 11 Pro Max" override --wifiBars 2 xcrun simctl status_bar "iPhone 11 Pro Max" override --wifiBars 33G に切り替える
xcrun simctl status_bar "iPhone 11 Pro Max" override --dataNetwork '3g'4G に切り替える
xcrun simctl status_bar "iPhone 11 Pro Max" override --dataNetwork '4g'LTE に切り替える
xcrun simctl status_bar "iPhone 11 Pro Max" override --dataNetwork 'lte'セルラーネットワークの信号強度を変更する
xcrun simctl status_bar "iPhone 11 Pro Max" override --cellularBars 0 xcrun simctl status_bar "iPhone 11 Pro Max" override --cellularBars 1 xcrun simctl status_bar "iPhone 11 Pro Max" override --cellularBars 2 xcrun simctl status_bar "iPhone 11 Pro Max" override --cellularBars 3 xcrun simctl status_bar "iPhone 11 Pro Max" override --cellularBars 4明/暗 モードを切り替える
シミュレーター内
- シミュレーターの設定アプリケーションを開く
Developer
を開く
Dark Appearances
をオンにする現在シミュレーターはダークモードになっています
Xcodeインターフェース内
- シミュレーターでアプリケーションを起動する
Xcode
プログラムツールバーでEnvironmental overrides
のアイコンを探すInterface Style
の隣のスイッチをオンにするバッテリーの状態を変更する
xcrun simctl status_bar "iPhone 11 Pro Max" override --batteryState 'charging' xcrun simctl status_bar "iPhone 11 Pro Max" override --batteryState 'charged' xcrun simctl status_bar "iPhone 11 Pro Max" override --batteryState 'discharging'バッテリー残量を変更する
xcrun simctl status_bar "iPhone 11 Pro Max" override --batteryLevel 0 xcrun simctl status_bar "iPhone 11 Pro Max" override --batteryLevel 100シミュレータに画像をアップロードする
シミュレータのウィンドウに直接画像ファイルをドラッグ&ドロップすることができます。
プッシュイベントのシミュレーション
まずは、ユーザーの通知を許可した状態で空白のiOSプロジェクトを開始します。iOSのターゲットのバンドルIDを、
com.demo.notification
として仮定します。
payload.apns
ファイル
payload.apns
という名前の空のファイルを作成します。このファイルは、通知の送信先となるアプリのターゲットとその通知内容をシミュレーターに指示します。この例では、
Hello, World
というシンプルなメッセージを、バンドルIDがcom.demo.notification
のアプリに送信するとします。//payload.apns { "Simulator Target Bundle": "com.demo.notification", "aps": { "alert": { "body": "ネコノヒー ???", "title": "こにちわ!" } } }このファイルをシミュレーターにドラッグアンドドロップします
シミュレータ上でアプリを実行します
通知の許可を承認します
このファイルをFinderからシミュレータにドラッグアンドドロップします
キャリア名を変更
(
iPhone 8 Plus
という名前のシミュレーターを実行していると仮定)xcrun simctl status_bar "iPhone 8 Plus" override --operatorName 'ネコ Mobile' --cellularMode activeスクリーンショット
キーボード上の
Command-s
キーを押すことができます。スクリーンショットはデスクトップ上に保存されます。動画を録画
xcrun simctl io booted recordVideo appVideo.movこのコマンドは現在実行中のシミュレーターの動画をスクリーンレコード(画面録画)し、
control-C
を押すとファイルappVideo.mov
を保存しますマウスカーソルを表示
defaults write com.apple.iphonesimulator ShowSingleTouches 1GUI app
Xcodeシミュレータを操作するのに役立つGUIアプリがあります
twostraws/ControlRoom: A macOS app to control the Xcode Simulator.
https://stackoverflow.com/a/60853266
https://stackoverflow.com/a/57989733
https://stackoverflow.com/a/41141801
xcrun simctl status_bar "iPhone 8 Plus" override --help
- 投稿日:2020-07-29T00:18:11+09:00
たった14行でiOSアプリ内のリンクをリッチに表示する方法
FacebookやTwitterでURLを投稿すると、リンク先のタイトルや画像を自動で取得してカードのようなUIとして表示されるのを見たことがあるでしょうか。そんな機能を簡単に実装できるApple標準のフレームワークがXcode11以降で使えるようになりました。
例えばYoutubeのリンク
Youtube動画の場合、リンクをアプリに埋め込むとそのまま再生できました。
LinkPresentationフレームワークを使うと、Youtube動画とかアプリ内でそのまま再生できるのね。https://t.co/iMYuqb2zaF pic.twitter.com/FxmEF6ygrA
— Natsui@?iOSエンジニア (@MeSummery) July 28, 2020LinkPresentation framework
URL からメタデータを取得し、アプリ内でリッチなリンクコンテンツをいい感じに表示してくれるAppleのフレームワーク。iOS 13.0以降から利用可能。
https://developer.apple.com/documentation/linkpresentation実装ステップ
利用箇所でまずフレームワークをインポートしておきましょう。
import LinkPresentationURLからメタデータを取得する
startFetchingMetadata(for:completionHandler:)
をコールしてメタデータの取得を開始します。let metadataProvider = LPMetadataProvider() let url = URL(string: "https://youtu.be/hMgcaYd2BZM")! // リッチに表示したいURL metadataProvider.startFetchingMetadata( for: url, completionHandler: { metadata, error in // Make use of fetched metadata. })
completionHandler
はバックグラウンドキューで実行されます。
クロージャー内でUIを操作する場合には、メインスレッドで行うようにしましょう。メタデータを専用Viewに受け渡す
LPMetadataProvider
から受け取ったメタデータをLPLinkView
の初期化時に渡します。metadataProvider.startFetchingMetadata( for: url, completionHandler: { metadata, error in if error != nil { return } guard let metadata = metadata else { return } DispatchQueue.main.async { // メインディスパッチキューで実行 let linkView = LPLinkView(metadata: metadata) // メタデータを渡す self.previewView.addSubview(linkView) // Storyboard上に配置した任意のUIView // Sizing } })今回は、生成した
LPLinkView
のインスタンスをStoryboard上に配置したpreviewView
にaddSubview
しました。
また、前述のとおり、completionHandler
内のUIの更新は、DispatchQueue.main
で実行しましょう。サイズを決定する
サイズを指定したら、
sizeToFit()
で任意のサイズにレイアウトを合わせましょう。linkView.frame.size = self.previewView.frame.size linkView.sizeToFit()今回は
linkView
のサイズをSuperview
に揃えましたが、任意のCGSize
を設定しても◎
これにて完成です。ソースコード全体
let metadataProvider = LPMetadataProvider() let url = URL(string: "https://youtu.be/hMgcaYd2BZM")! metadataProvider.startFetchingMetadata( for: url, completionHandler: { metadata, error in if error != nil { return } guard let metadata = metadata else { return } DispatchQueue.main.async { let linkView = LPLinkView(metadata: metadata) self.previewView.addSubview(linkView) linkView.frame.size = self.previewView.frame.size linkView.sizeToFit() } })ぴったり14行✌️?
まとめ
iOS14のリリースを(おそらく)9月に控え、最新OSを2,3世代サポートしているアプリは、やっとiOS13以降のフレームワークを本格的に導入していけることと思います。
LinkPresentationは たった十数行でアプリのUXを向上できるフレームワークなので、ぜひ活用していきたいですね。このフレームワークについては、2019年のWWDCビデオもあります。
ビデオの長さは6分前後なので、気軽に見られておすすめです。
今回の記事は触れないローカルキャッシュの取得や共有時の実装のポイントに触れられています。
https://developer.apple.com/videos/play/wwdc2019/262/以上です
ありがとうございました。