- 投稿日:2020-09-20T21:46:14+09:00
[Swift] protocol制約をかけた型で"Cannot use mutating member on immutable value"と言うエラーが出る場合の対処。
swift5で次のコードを実行すると
Cannot use mutating member on immutable value: 'hoge' is a 'let' constant
と言うエラーが出ます。これにしばらくハマってしまったので解決方法を書いておきます。
protocol Hoge{ var items:[String]{get set} } class Fuga:Hoge{ var items: [String] init(_ items: [String]){ self.items = items } } class Piyo:Hoge{ var items: [String] init(_ items: [String]){ self.items = items } } var hoges:[Hoge] = [Fuga(["a"]), Piyo(["a"]), Fuga(["a"])] hoges.forEach{ (hoge: Hoge) in hoge.items.append("b") //エラー:Cannot use mutating member on immutable value: 'hoge' is a 'let' constant } print(hoges.map{$0.items})
items
は{get set}
で宣言しており、問題はないように見えますが、エラーではhoge
が定数だと言っています。forEach
内で変更しているのが問題なわけでもなく、実際次のコードはすんなり動きます。var hoges:[Fuga] = [Fuga(["a"]), Fuga(["a"]), Fuga(["a"])] hoges.forEach{ (hoge: Fuga) in hoge.items.append("b") }このエラーの原因は
protocol
に準拠した型がclass
かstruct
か分からないことです。struct
は基本的に不変なので、もしもHoge
に準拠した型がstruct
だった場合変更ができなくなってしまいます。ということで、対応には
protocol
にclass
の制約をかけてあげることです。protocol Hoge:class{ //ここが大事!!!! var items:[String]{get set} } class Fuga:Hoge{ var items: [String] init(_ items: [String]){ self.items = items } } class Piyo:Hoge{ var items: [String] init(_ items: [String]){ self.items = items } } var hoges:[Hoge] = [Fuga(["a"]), Piyo(["a"]), Fuga(["a"])] hoges.forEach{ (hoge: Hoge) in hoge.items.append("b") } print(hoges.map{$0.items})以上です。
- 投稿日:2020-09-20T21:30:13+09:00
DockerでReact Native(TypeScript)+Expoのプロジェクト構築
まえおき
React Native+Expoで構成されたプロジェクトのDockerコンテナをMac OS X上に構築する手順を記載しています。
各端末の情報
PC
- Mac OS Catalina Ver.10.15.6
- docker version 19.03.12, build 48a66213fe
- docker-compose version 1.26.2, build eefe0d31
iPhone
- iPhone XR
- iOS:13.7
ExpoClientで動作検証済みの端末
- iPhone(iOS:13.7)
前提
- docker, docker-compose導入済み
手順
1. Expoアカウントを作成します
2. Expoクライアントアプリのインストールとセットアップをおこないます。
iPhoneでExpoクライアントアプリのインストールとセットアップ方法
3. Docker環境を構築します
ファイル構成
root └── docker └── react_native └── dockerfile └── docker-compose.yml └── .envdocker/react_native/dockerfile
FROM node:14-alpine WORKDIR /usr/src/app/ RUN apk update && apk add bash RUN yarn global add expo-clidocker-compose.yml
version: "3" services: react_native: build: ./docker/react_native volumes: - ./react_native/:/usr/src/app env_file: .env command: yarn start ports: - "19000:19000" - "19001:19001" - "19002:19002".env
Expoを利用する各端末のIPなどを設定する必要があります。
- ADB_IP
- 検証端末のIPアドレスを指定してください。カンマ区切りで複数指定可能なようです。
- REACT_NATIVE_PACKAGER_HOSTNAME
- Dockerコンテナ可動端末のIPアドレス
例ADB_IP=192.168.0.10,192.168.0.11,... REACT_NATIVE_PACKAGER_HOSTNAME=192.168.0.24. Dockerコンテナをビルドします
docker-compose build5. Dockerコンテナへ接続します
docker-compose run --rm react_native bash --login6. expoプロジェクトを作成します
expo init .7. プロジェクトテンプレートを選択するとプロジェクトのセットアップが開始されます
わたしは[blank (TypeScript)]を選択しました。
? Choose a template: (Use arrow keys) ----- Managed workflow ----- blank a minimal app as clean as an empty canvas ❯ blank (TypeScript) same as blank but with TypeScript configuration tabs several example screens and tabs using react-navigation ----- Bare workflow ----- minimal bare and minimal, just the essentials to get you started minimal (TypeScript) same as minimal but with TypeScript configuration8. セットアップが完了したらコンテナから抜けます
9. Dockerコンテナを起動します
docker-compose up10. 表示されたQRコードを検証端末上で読み取ります
11. 検証端末でExpo Clientアプリが起動しREACTの画面が表示されます
12. react_native/App.tsxを更新すると・・・
react_native/App.tsxのファイル内に記述された表示テキストの末尾に☺️を追加してファイルを更新します。
13. 更新した内容が検証端末へ自動的に反映されます
ホットリロードによって末尾の☺️がiPhone上の検証画面へ自動的に反映されます。
参考
DockerでReact Native環境作成から、Expo Clientで実機確認するまで
WSLでReact Native + Expo環境を作ろう
DockerでExpo / React Nativeを実行する
- 投稿日:2020-09-20T21:12:54+09:00
iPhoneでExpo Clientのインストールとセットアップ
まえおき
React Nativeの開発支援サービスExpoの検証用クライアントアプリケーションのiPhoneでのインストールとセットアップ方法を記載しています。
EXPOアカウントの登録手順
別の記事に手順を掲載しています。
Expoアカウントの作成方法手順
- 投稿日:2020-09-20T20:32:48+09:00
UIAlertViewのようにいつでもどこでも必ず表示されるアラートを実現
問題点
今更ながらUIAlertViewがdeprecatedになった警告に対応しました。
'UIAlertView' is deprecated: first deprecated in iOS 9.0 - UIAlertView is deprecated.という警告ですね。
どう変えればいいかはググればいっぱい出てくるので割愛しますが、問題点は・・・
- 表示対象のUIViewControllerが必要。
- 二つのUIViewControllerを一つのUIViewController常に
presentViewController
できない。という問題です。
例えば、どこかのUIViewController内で表示してるのであれば、
UIAlertController *alert = [UIAlertController alertControllerWithTitle: title message: message preferredStyle: UIAlertControllerStyleAlert]; UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style: UIAlertActionStyleDefault handler: handler]; [alert addAction: ok]; [self presentViewController:alert animated:YES completion:nil];といった感じで表示できますが、昔のUIAlertViewはどこからでも表示できたので、例えばModelの中などでも使用されてたり、UIViewControllerが取得できないdelegateの中で使用されてたりして困りました。
そこでAPPからrootControllerを取得してそこに表示すればええやん!ってことでやってみました。
UIViewController *rootController = [[[[UIApplication sharedApplication]delegate] window] rootViewController]; [rootController presentViewController:alert animated:YES completion:nil];こういう感じですね。これで表示はされるのですが、同じくUIPopoverControllerも同じ
presentViewController:alert
を使って表示される仕組みに変わっていて、それがrootController
に表示された状態同じようにアラートを出そうとするとWarning: Attempt to present <UIAlertController ....> ... which is already presentingのような警告がでて無視されちゃうんですね。Modelの中で色々使いまわされてるので、どんなシチュエーションでも必ず表示されるアラートが欲しい!というわけで色々試した結果いけそうなのができたので共有します。
解決策
UIAlertController *alert = [UIAlertController alertControllerWithTitle: title message: message preferredStyle: UIAlertControllerStyleAlert]; UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style: UIAlertActionStyleDefault handler: nil]; [alert addAction: ok]; UIViewController *rootController = [[[[UIApplication sharedApplication]delegate] window] rootViewController]; if(rootController.presentedViewController != nil){ [rootController.presentedViewController presentViewController:alert animated:YES completion:nil]; } else { [rootController presentViewController:alert animated:YES completion:nil]; }まあ、単純な話ですが、既にpresentedViewControllerがあったらそこに表示、なければrootに表示するだけです。
みんな大好きStackOverFlowで見つけました。サイトはSwiftのコードですね。
- 投稿日:2020-09-20T16:07:03+09:00
大規模なiOSアプリ開発を2年以上継続して得られた知見の共有
前書き
それなりに大規模なアプリの新規開発〜機能追加を行う中で得られた知見をまとめます。
アプリのジャンル/ライフサイクル、チームメンバーのスキルレベルなどによって適用できない事項もあるかと思いますが、一つの事例として参考にしていただければ幸いです。
<アプリ/チームの概要>
- iOS版開発チームとしては最小4人〜最大9人。
- その他、Androidチーム、バックエンドチーム、デザインチーム…などなど諸々合わせて総勢20人〜30人
- アプリの累計ダウンロード数は数百万。
- App Store上のカテゴリは「ファイナンス」。
- リリースサイクル(計画リリース)は平均で2ヶ月に1回。
- 開発環境はXcode + Swift。
- Scrumで開発。
本文・コメント含め、これ以上に具体的なことは書けませんのでご了承ください。
本記事の内容は内容はあくまで私個人の見解であり、所属企業における立場、戦略、意見を代表するものではありません。UI構築
ポリシー
- 一時期はStoryboardと、コードベース・レイアウトが混在していた時期もありましたが、現在ではコードベース・レイアウトのみに統一しました。
- 理由は以下のようなStoryboardのデメリットを感じることが多くなってきたためです。
- 人数が多いとStoryboardのconflictが多く、その解消がとにかく面倒臭い。
- Storyboardでは、画面修正のレビューが辛い。
- アプリ規模が大きくなるにつれ、Xcode上でStoryboardを開く時の待ち時間が長くなってしまった。
- デザイナーからのUI/UX要求レベルが上がってきて、画面の状態が複雑になってきた。
- 例えば、ローディングプレースホルダを表示しつつ裏でAPI通信>取得成功時は通常View、エラー時はエラー用の特殊なView、など。。。
- Storyboardでは静的な状態はプレビューできるが、上のような動的な状態変化が多いと意味がない。
- Storyboardでは、フォント、色など、アプリの統一ポリシーを適用し忘れることがしばしばある。
- ただし、Unwind Segueは便利なので、画面遷移はStoryboardを使っています。
- コードベース・レイアウトを容易にするために、自作ライブラリを構築しました(productionコードなので公開はできません)。
参考リンク:
iOSアプリケーションでコードベースのレイアウトを積極利用する
[Xcode] [Swift] 実務的Tips: Unwind Segueで2つ以上前の画面に一気に戻って画面を再更新する評価
- コードベース・レイアウト統一に至るまでに紆余曲折はありましたが、それが生産性・品質・保守性ともにベストな方法である、と評価しています。
- ただし、画面遷移のみStoryboardに依存している状態はあまり「見通し」がよくないので、改善の余地がありそうです。
アーキテクチャー・パターン
ポリシー
- 当初は標準的なCocoa MVCで作っていました。当然FatViewController化しました。
- アプリの規模が大きくなり、またエンハンスメントを重ねるごとに改修が困難になってきました。
- このため、MVVMへのリアーキテクチャーを進めました。
- 一気に行わず、新規機能や大規模改修に合わせて実施。
- ライブラリは使わず、設計パターンだけを適用。
- MVVMアーキテクチャーを選定した理由:
- Clean Architectureなどの複雑なアーキテクチャーよりも、MVVMへの変更の方が改修規模が小さかったため。
- メンバーのスキルレベルに差があり、MVVMより複雑なアーキテクチャーを全員が習熟することは困難であったため。
(具体的な実装例は追って別記事を投稿する予定です。)
評価
- 保守性・拡張性が上がったと評価しており、今後も継続する予定です。
ライブラリ管理
ポリシー
- ライブラリに起因するトラブルは結構多いので、ライブラリ導入は必要最小限に止めるようにしています。
- ライブラリ管理ツールとしてCarthageを使っています。
- CocoaPodsよりもビルドが早いのでメリットを感じて導入しました。
評価
- ライブラリに起因するトラブルは開発計画を大きく狂わせるので、今後も必要最小限に止める方針に変わりないと思います。
- Carthageについては、2020年9月現在でXcode 12でビルドエラーになるというクリティカルな問題が発生しているので、CocoaPodsに近日中に乗り換えるかもしれません。。。
- 大規模アプリにおいては、ライブラリ管理ツール、導入ライブラリ共に、その選定は慎重にならざるを得ないです。
コードレビュー
ポリシー
- IBM Cloud上にGitLabを導入しました。
- コードレビューは99.9%実施しています。
- GitLabのマージリクエスト上でレビューコメントをやりとりするスタイルです。
- レビューアーは原則として複数人としています。
- 一次レビューはメンバー
- 最終レビューはリーダー
- コードレビューの目的は以下の通りと宣言しており、その観点で気になったことがあればレビューコメントを書くようにしています。
- システムのメンテナンス性、リーダビリティ、理解のしやすさを改善すること。
- ブラックボックステストでは検出しづらい不具合(例:メモリーリーク)を発見すること。
- 知識を共有すること。
- 一応、コーディングガイドラインはありますが項目は最低限です。
- 「強制アンラップは理由がない限りは使わないようにしよう」「インデントは合わせよう」「Xcodeの設定を合わせよう」程度です。
- 私見ですが、ガチガチに縛ろうとして規約を増やしたところで、読むことが大変になるだけで、完璧に守ることは困難です。
- 規約で縛るよりも、上のような「目的」を共有することの方が大事では、と考えます。
参考リンク:
[Xcode] 実務的Tips: チーム内でXcodeの設定項目を合わせて不要な修正差分が出ないようにする評価
- 品質・保守性には大きな効果が認められ、コードレビューを行わないという選択肢は今後もありません。
- 以下の点は要改善ポイントです。
- リーダーの負荷が高いこと(レビューに追われて自分の担当分の実装時間が削られる)。
- リーダーがボトルネックになること。
- リーダーが不在だとマージできない。
- 先行タスクのマージリクエストがレビュー未完了だと後続作業が滞る。
テスト
ポリシー
- 1年ぐらい、XCUITestによるテストの自動化に取り組みました。→詳細は「参考リンク」の記事を参照
- しかしながら、機能改修時のメンテナンスコストがあまりにも大きかったです。
- コード修正は1時間でも、既存のテストの修正に半日以上かかることもザラ。。。
- このため、現在では以下のような手法を取っています。
- ロジック部分のテストはXCTest。
- UI部分のテストは実動作で確認。
- APIについては、Node.jsベースのスタブツール(ローカルサーバー)を自作し、正常系/異常系レスポンスのテストを行う。
- 以上は開発チームとしてのテストで、業務観点での総合テストは別途QAチームがテストシナリオに即して行う。
参考リンク:
XcodeのUIテストフレームワーク「XCUITest」のTips評価
- 私たちのプロダクトではUIの改変が多いため、XCUITestは費用対効果の観点で合いませんでした。
- MVVMパターンへのリアーキテクチャーとの「合わせ技」で、なるべくView/ViewControllerには画面表示以外のロジックは書かないようにし、ViewModelのXCTestを増やすように取り組んでいるところです。
CI/CD
ポリシー
- 以下の目的で、CI/CDを取り入れています。
- Sprintの途中であっても、マージされた機能はいち早くQAエンジニアに渡してテストしてもらいたい。
- あるいは、オーナーやデザイナーに動かしてもらい、フィードバックしてもらいたい。
- 現状は、JenkinsでGitLabのブランチを監視して、fastlaneをキックしてビルドを走らせ、TestFlightにアップロードしています。
- テストは自動で走らせるものの、失敗はSlackに自動postするだけで、デプロイは止めません。
- 緊急のバグ修正時などはテストコードの修正は後回しにするケースもあるので…
評価
- アプリの規模が大きくなるに応じてビルド時間が長くなるので、大規模アプリでは自動デプロイは必須です。
後書き
- DX時代が到来し、各企業とも顧客とのエンゲージメント向上のためにスマホアプリを活用する例は多く、ライバルに遅れを取らないためには高・多機能なアプリを早いサイクルでリリースすることが求められています。
- しかしながら、OSも開発環境も絶えず進化している中で、大規模なアプリを、迅速かつトラブルなくリリースし続けることは容易ではありません。
- それを成し遂げるのためには「完璧な手法をじっくり作り上げること」ではなく「早いサイクルで小さい改善を積み重ねること」と考えています。
- 投稿日:2020-09-20T16:07:03+09:00
大規模なiOSアプリ開発を2年以上継続して得られた知見
前書き
それなりに大規模なアプリの新規開発〜機能追加を行う中で得られた知見をまとめます。
アプリのジャンル/ライフサイクル、チームメンバーのスキルレベルなどによって適用できない事項もあるかと思いますが、一つの事例として参考にしていただければ幸いです。
<アプリ/チームの概要>
- iOS版開発チームとしては最小4人〜最大9人。
- その他、Androidチーム、バックエンドチーム、デザインチーム…などなど諸々合わせて総勢20人〜30人
- アプリの累計ダウンロード数は数百万。
- App Store上のカテゴリは「ファイナンス」。
- リリースサイクル(計画リリース)は平均で2ヶ月に1回。
- 開発環境はXcode + Swift。
- Scrumで開発。
本文・コメント含め、これ以上に具体的なことは書けませんのでご了承ください。
本記事の内容は内容はあくまで私個人の見解であり、所属企業における立場、戦略、意見を代表するものではありません。UI構築
ポリシー
- 一時期はStoryboardと、コードベース・レイアウトが混在していた時期もありましたが、現在ではコードベース・レイアウトのみに統一しました。
- 理由は以下のようなStoryboardのデメリットを感じることが多くなってきたためです。
- 人数が多いとStoryboardのconflictが多く、その解消がとにかく面倒臭い。
- Storyboardでは、画面修正のレビューが辛い。
- アプリ規模が大きくなるにつれ、Xcode上でStoryboardを開く時の待ち時間が長くなってしまった。
- デザイナーからのUI/UX要求レベルが上がってきて、画面の状態が複雑になってきた。
- 例えば、ローディングプレースホルダを表示しつつ裏でAPI通信>取得成功時は通常View、エラー時は特殊なView、など。。。
- Storyboardでは静的な状態はプレビューできるが、上のような動的な状態変化が多いと意味がない。
- Storyboardでは、フォント、色など、アプリの統一ポリシーを適用し忘れることがしばしばある。
- ただし、Unwind Segueは便利なので、画面遷移はStoryboardを使っています。
- コードベース・レイアウトを容易にするために、自作ライブラリを構築しました(productionコードなので公開はできません)。
参考リンク:
iOSアプリケーションでコードベースのレイアウトを積極利用する
[Xcode] [Swift] 実務的Tips: Unwind Segueで2つ以上前の画面に一気に戻って画面を再更新する評価
- コードベース・レイアウト統一に至るまでに紆余曲折はありましたが、私たちのアプリではコードベース・レイアウトが生産性・品質・保守性ともにベストな方法である、と評価しています。
- ただし、画面遷移のみStoryboardに依存している状態はあまり「見通し」がよくないので、改善の余地がありそうです。
アーキテクチャー・パターン
ポリシー
- 当初は標準的なCocoa MVCで作っていました。当然FatViewController化しました。
- アプリの規模が大きくなり、またエンハンスメントを重ねるごとに改修が困難になってきました。
- このため、MVVMへのリアーキテクチャーを進めました。
- 一気に行わず、新規機能や大規模改修に合わせて実施。
- ライブラリは使わず、設計パターンだけを適用。
- MVVMアーキテクチャーを選定した理由:
- Clean Architectureなどの複雑なアーキテクチャーよりも、MVVMへの変更の方が改修規模が小さかったため。
- メンバーのスキルレベルに差があり、MVVMより複雑なアーキテクチャーを全員が習熟することは困難であったため。
(具体的な実装例は追って別記事を投稿する予定です。)
評価
- 保守性・拡張性が上がったと評価しており、今後も継続する予定です。
ライブラリ管理
ポリシー
- ライブラリに起因するトラブルは結構多いので、ライブラリ導入は必要最小限に止めるようにしています。
- ライブラリ管理ツールとしてCarthageを使っています。
- CocoaPodsよりもビルドが早いのでメリットを感じて導入しました。
評価
- ライブラリに起因するトラブルは開発計画を大きく狂わせるので、今後も必要最小限に止める方針に変わりないと思います。
- Carthageについては、2020年9月現在でXcode 12でビルドエラーになるというクリティカルな問題が発生しているので、CocoaPodsに近日中に乗り換えるかもしれません。。。
- 大規模アプリにおいては、ライブラリ管理ツール、導入ライブラリ共に、その選定は慎重にならざるを得ないです。
コードレビュー
ポリシー
- IBM Cloud上にGitLabを導入しました。
- コードレビューは99.9%実施しています。
- GitLabのマージリクエスト上でレビューコメントをやりとりするスタイルです。
- レビューアーは原則として複数人としています。
- 一次レビューはメンバー
- 最終レビューはリーダー
- コードレビューの目的は以下の通りと宣言しており、その観点で気になったことがあればレビューコメントを書くようにしています。
- システムのメンテナンス性、リーダビリティ、理解のしやすさを改善すること。
- ブラックボックステストでは検出しづらい不具合(例:メモリーリーク)を発見すること。
- 知識を共有すること。
- 一応、コーディングガイドラインはありますが項目は最低限です。
- 「強制アンラップは理由がない限りは使わないようにしよう」「インデントは合わせよう」「Xcodeの設定を合わせよう」程度です。
- 私見ですが、ガチガチに縛ろうとして規約を増やしたところで、読むことが大変になるだけで、完璧に守ることは困難です。
- 規約で縛るよりも、上のような「目的」を共有することの方が大事では、と考えます。
参考リンク:
[Xcode] 実務的Tips: チーム内でXcodeの設定項目を合わせて不要な修正差分が出ないようにする評価
- 品質・保守性には大きな効果が認められ、コードレビューを行わないという選択肢は今後もありません。
- 以下の点は要改善ポイントです。
- リーダーの負荷が高いこと(レビューに追われて自分の担当分の実装時間が削られる)。
- リーダーがボトルネックになること。
- リーダーが不在だとマージできない。
- 先行タスクのマージリクエストがレビュー未完了だと後続作業が滞る。
テスト
ポリシー
- 1年ぐらい、XCUITestによるテストの自動化に取り組みました。→詳細は「参考リンク」の記事を参照
- しかしながら、機能改修時のメンテナンスコストがあまりにも大きかったです。
- コード修正は1時間でも、既存のテストの修正に半日以上かかることもザラ。。。
- このため、現在では以下のような手法を取っています。
- ロジック部分のテストはXCTest。
- UI部分のテストは実動作で確認。
- APIについては、Node.jsベースのスタブツール(ローカルサーバー)を自作し、正常系/異常系レスポンスのテストを行う。
- 以上は開発チームとしてのテストで、業務観点での総合テストは別途QAチームがテストシナリオに即して行う。
参考リンク:
XcodeのUIテストフレームワーク「XCUITest」のTips評価
- 私たちのプロダクトではUIの改変が多いため、XCUITestは費用対効果の観点で合いませんでした。
- MVVMパターンへのリアーキテクチャーとの「合わせ技」で、なるべくView/ViewControllerには画面表示以外のロジックは書かないようにし、ViewModelのXCTestを増やすように取り組んでいるところです。
CI/CD
ポリシー
- 以下の目的で、CI/CDを取り入れています。
- Sprintの途中であっても、マージされた機能はいち早くQAエンジニアに渡してテストしてもらいたい。
- あるいは、オーナーやデザイナーに動かしてもらい、フィードバックしてもらいたい。
- 現状は、JenkinsでGitLabのブランチを監視して、fastlaneをキックしてビルドを走らせ、TestFlightにアップロードしています。
- テストは自動で走らせるものの、失敗はSlackに自動postするだけで、デプロイは止めません。
- 緊急のバグ修正時などはテストコードの修正は後回しにするケースもあるので…
評価
- アプリの規模が大きくなるに応じてビルド時間が長くなるので、大規模アプリでは自動デプロイは必須です。
後書き
- OSも開発環境も絶えず進化している中で、大規模なアプリを、迅速かつトラブルなくリリースし続けることは容易ではない、と感じます。
- 「早いサイクルで小さい改善を積み重ねる」をモットーに、まだまだ模索を続けて行こうと考えています。
- 投稿日:2020-09-20T14:27:47+09:00
ARCoachingOverlayViewでユーザーにデバイスをうごかしてもらって、ARKitに世界情報をあたえる
ARKitがWorldTrackingを確立するには、デバイスを動かして、ARKitに視点を与える必要があります。
ARCoachingOverlayViewでユーザーにガイダンスを出して、デバイスをうごかしてもらいます。
1、ARCoachingOverlayViewを初期化します。
let coachingOverlay = ARCoachingOverlayView()ARCoachingOverlayViewの設定
coachingOverlay.goal = .anyPlane //情報を取る目標設定 // 可能な値 case anyPlane case horizontalPlane case tracking case verticalPlane coachingOverlay.activatesAutomatically = true //Tracking状態が不十分になると、再度コーチングするか // セッションとデリゲートを設定 coachingOverlay.session = sceneView.session coachingOverlay.delegate = self // Viewとして扱う coachingOverlay.frame = sceneView.bounds sceneView.addSubview(coachingOverlay)2、ARCoachingOverlayViewDelegateを設定
コーチングの状態によって呼ばれるDelegate functionは以下
func coachingOverlayViewWillActivate(_ coachingOverlayView: ARCoachingOverlayView) { // コーチングが表示される前に呼ばれる。ここでコーチング中操作できないButtonなどを非表示にする。 } func coachingOverlayViewDidDeactivate(_ coachingOverlayView: ARCoachingOverlayView) { // コーチングが終了したあとに呼ばれる。ここでコーチング中操作できないButtonなどを再表示する。 }これでARSessionをrunすると動くはずです。
必要な情報が得られたら、コーチングは消えます。
このステップをやったほうが、正確なワールドトラッキングが得られます。
Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。
- 投稿日:2020-09-20T11:29:13+09:00
iOSDC 2020 前夜祭に参加しました。
概要
iOSDCに参加しました。
前夜祭の内容になっています。少し遅れてしまい2つしか見ていないですがメモ程度に残します。
見たトークは
- Call Directory Extension詳解
- あなたの知らない連絡先の世界
です。
Call Directory Extension詳解
プロポーザルはこちら
- Call Directory Extensionとは発信者名表示とか出せる機能
- 黎明期の時はすごい発展したのに、最近はバグなどがあってもAppleが対応しないという悲壮感が面白い発表でした笑
- Call Directory Extensionの利用の際にユーザー許可してもらうところの説明は丁寧にやるように気を付けるなど、実践者ならではの具体的なアドバイスがよかったです。
- 息をするようにバグが出るみたいです
初めての情報がいっぱいで、実際に商用開発されている方ならではの話が聞けて面白かったです!
あなたの知らない連絡先の世界
- ミドルネームや3世などどういう風に連絡先に入るのか。サーバーに姓名だけ入れといて大丈夫?笑
- 電話番号のバリデーションを数字だけにするとダメ!記号とか英語も使えるし、記号の使い方はiphoneユーザとしてもすごく勉強になったし面白かったです。
- iOSはvCard形式で、連絡先の情報の構造の話がよかった
- PersonNameComponentsFormatterを使うと人の名前の姓名の分割などができる。Foundationに入っているので気楽に使えると#askthespeakerでおっしゃってました。
- 連絡先の履歴がiOS13から取得できるようになったとのこと、この機能はobjective-Cでしか使えず。裏番組もobjective-Cの話題だったので、iOSDCではなくobjective-C-DCだ!
発表がユーモアがあってすごく面白かったです Day2でも登壇されるとのことで期待!
まとめ
iOSちょっとかじったくらいでも面白かったです。
DAY1、DAY2も楽しみたい。
- 投稿日:2020-09-20T11:24:00+09:00
iOSDC 2020 メモ
Day 01
Track D - iOSには無いmacOS独自機能をCatalystで実装する @fromkk
3 メニュータイプ
* メニュー
* タッチバー
* ツールバーサンプル
https://github.com/fromkk/CatalystSampler
動画:
https://www.youtube.com/watch?v=_7FfMCEBPiY&feature=youtu.be
Track B - 400種類のアプリを毎日ビルドする自動化の技術 @k_katsumi
ビルド・申請作業とは
ワークフロー関係者
Dependabot良いですね!
https://dependabot.com/スライド
Track B - ファッション業界を技術で変える、ZOZOの挑戦〜CTOが語る理想の組織像とは〜 @kyuns
ご飯タイム
もうちょっと採用などの作戦とか聞きたかったな〜
Track B - デバッグメニューのメンテナンスが大変だったので、専用アプリを作りました @FromAtom
https://speakerdeck.com/fromatom/iosdc-japan-2020
App Groupsを利用してデータシェアする
供用のUserDefaultsを利用してDebugメニューアプリでコントロール
コツ
UIの実装は面倒、UIを生成コードで楽にする
サンプル
https://github.com/FromAtom/iosdc-2020-sample
意見
複数のアプリ結構便利そうだけど一つしかない場合Developerメニュー作成すべきかな
コード反対しているところミスったら結果は一緒と思って?Track B - ベジェ曲線の知らない世界 @takoikatakotako
https://qiita.com/takoikatakotako/items/39e3d46dd9f7a700c0b3
ムズッ
Track B - GitHub ActionsでiOSアプリをCIする個人的ベストプラクティス @the_uhooi
https://speakerdeck.com/uhooi/iosdc-2020
CIのメリット
1. リポジトリーにエラーが含まれていないのを保証
2. 自動で何か実行できる(手間かからない)
3. 誰かのローカルに頼らない
4. 結果を簡単に確認できる!デメリット
1. 学習コスト
2. 色々なサービスがユニークなワークフロー・書き方がある(CircleCI, Bitrise, GitHub Actions)サンプル
https://github.com/uhooi/iOSDC2020-Talk-Sample
あとはGitHub Actionsライブコーディング!
┌|▼▼|┘ ┌|▼▼|┘ ┌|▼▼|┘ ┌|▼▼|┘ ┌|▼▼|┘
Track B - 効率よくUIKitからSwiftUIへ移行する @yhkaplan
Slides: https://speakerdeck.com/yhkaplan/migrating-from-uikit-to-swiftui-efficiently
YouTube (English): https://youtube.com/watch?v=kedKk96SXxA
YouTube (Japanese): https://youtube.com/watch?v=Mavk5AQAz7U
Source: https://github.com/yhkaplan/presentations/tree/main/2020/09/20
色々大変そうですね。。。
Architecture
1. Redux
2. The Composable Architecture
3. MVVMTrack A - LT
Group 1
Catalystに対応したアプリをリリースするまでのリジェクト集
https://speakerdeck.com/fromkk/iosdc-2020-lt
Apple Pencilと左利き対応
https://speakerdeck.com/kwzr/apple-penciltozuo-li-kidui-ying
DroidKaigiの公式アプリで始める_iOSアプリOSSコミッターへの道
https://speakerdeck.com/entaku/droidkaigifalsegong-shi-ahuriteshi-meru-iosahuriosskomitutahefalsedao
iOS Custom Keyboardsでできること/できないこと/やってはいけないこと
https://speakerdeck.com/kyome22/iosdc-japan-2020-lt
https://github.com/Kyome22/IronKeyboardGroup 2
Copyable PDF作るには
https://github.com/EndouMari/SampleScreenshot
あなたのアプリ、✨リブランディング✨できますか?
https://speakerdeck.com/monoqlo/iosdc2020
Day 02
Track B - Xcode PreviewでUIKit @kenmaz
iOS13未満切らないと使えないのでまだまだっか〜
二つの重要なポイント
1. UIViewRepresentable/UIViewControllerRepresentable
2. PreviewProvider同時に多言語の画面確認できる?!
後で導入してみよう〜
Track D - iOSアプリ開発のためのThe Composable Architectureがすごく良いので紹介したい @yimajo
4 Important Points
1. State Mgmt
2. Composition
3. Side Effect
4. TestableTrack A - 大解剖!UIColorファミリー @S_Shimotori_pub
https://speakerdeck.com/s_shimotori/uicolor-anatomy
https://speakerdeck.com/s_shimotori/uicolor-clusterUIColor 18サブクラスある!
Track E - SwiftのWebAssembly対応の軌跡 @kateinoigakukun
https://speakerdeck.com/kateinoigakukun/the-state-of-swift-webassembly
Optimize後 3.5MBまで持っていけてすごいな!
Track B - SwiftUI時代の Functional iOS Architecture @inamiy
後でゆっくり考えるw
Track E - Apple Silicon への長い道 @hak
omoroi
LT大会
LLDB
pvc
tv
vinfoiOS 13におけるSiri Shortcuts 最小実装+α
https://speakerdeck.com/myamada04/ios-13niokerusiri-shortcuts-zui-xiao-shi-zhuang-plus-axcrun Essentials
便利そう
今度調べてみよう!SwiftでわかるSOLID原則
https://speakerdeck.com/k_koheyi/swifttewakarusolidyuan-ze-iosdc-2020CryptoKitとCoreBluetoothを利用したスマートキー開発
https://speakerdeck.com/saiten/iosdc2020着信時氏名表示させたいエンジニア vs 簡単には着信時氏名表示できない電話番号
https://speakerdeck.com/kotetuco/iosdcjapan-2020-lt-calldirectory参加できなかったトーク資料
4年間運用されて表示速度が低下した詳細画面を改善する過程で得た知見 @marty_suzuki
https://speakerdeck.com/martysuzuki/iosdc-japan-2020-day-1-track-b-10-50
Background Notificationで新聞紙面の大きい画像の自動ダウンロードを実現する @shimastriper
そろそろCombine @shiz
スライド
https://speakerdeck.com/shiz/sorosorocombine補足資料
https://github.com/stzn/CombineStudyiPadOSでマウス・キーボード対応アプリを作る
https://speakerdeck.com/cc4966/ipados-app-using-pointer-and-keyboard
iOSではじめるWebAR
https://speakerdeck.com/ikkou/webar-in-ios
iPadOSDC: Multiple Windows
https://speakerdeck.com/hironytic/ipadosdc-multiple-windows
ConcurrencyWithGCD
https://speakerdeck.com/taka1068/concurrencywithgcd
SwiftでのConcurrent Map(並行処理map)の実装について
https://taka1068.hatenablog.jp/entry/2020/09/20/034600
iOSエンジニアだし、Androidアプリも作れるでしょ?
https://speakerdeck.com/akatsuki174/iosensiniatasi-androidahurimozuo-rerutesiyo
Migrate Swift 4.2 to 5.2
https://speakerdeck.com/shomasegi/migrate-swift-4-dot-2-to-5-dot-2
iOSリジェクト戦記
https://speakerdeck.com/hcrane/iosdc2020-iosriziekutozhan-ji
iOS のキーボードと文字入力のすべて
https://speakerdeck.com/niw/ios-falsekibodotowen-zi-ru-li-falsesubete
Webとネイティブアプリの付き合い方を改めて考える
https://speakerdeck.com/kiwi26/native-apps-and-web
SwiftUIを導入したアプリ設計
https://speakerdeck.com/yuta24/swiftuiwodao-ru-sitaapurishe-ji
実践!「みてね」における自動生成活用例
https://speakerdeck.com/ushisantoasobu/shi-jian-mitene-niokeruzi-dong-sheng-cheng-huo-yong-li
iOSアプリは「感情」を宿すのか? AIとアプリの未来について
https://speakerdeck.com/yukinaga/iosapuriha-gan-qing-wosu-sufalseka-aitoapurifalsewei-lai-nituite
Swiftで始める静的解析
https://speakerdeck.com/matsuji/swiftdeshi-merujing-de-jie-xi
アプリのパフォーマンスを継続的に計測する
https://speakerdeck.com/kariad/apurifalsepahuomansuwoji-sok-de-niji-ce-suru
Micro Modular Architecture with Bazel
https://speakerdeck.com/ra1028/micro-modular-architecture-with-bazel
Synchronized iPhones, Again!
https://speakerdeck.com/toyship/synchronized-iphones-again
google/mediapipe で始めるARアプリ開発/iOSDC2020
https://speakerdeck.com/noppefoxwolf/iosdc2020
実装したくなる音声編集
https://speakerdeck.com/yoseiyamagishi/shi-zhuang-sitakunaruyin-sheng-bian-ji
テストコードが増えるとバグは減るのだろうか?
https://speakerdeck.com/ahiru/does-more-test-code-mean-fewer-bugs
良いリンク
https://consim.design/
https://dependabot.com/
https://dev.to/natterstefan/how-to-add-a-readme-to-your-github-profile-2bo9
https://qiita.com/SnowCait/items/7a30ff80be70a739915c
- 投稿日:2020-09-20T11:17:08+09:00
XCTSkipの使い方まとめ
はじめに
Xcode11.4からXCTestフレームワークに新しく導入されたプロパティの一つに「XCTSkip」があります。
XCTSkipを使用することで明示的に「スキップ」の結果を出力することができます。
特に統合テストにおいては、必要条件や依存関係が必ずと言っていいほどあるかと思います。
例えばアプリケーションがiPad特有の機能を持っている場合はiPhoneではテストできませんし古いOSでは利用できないAPIを用いる場合テスト対象は必然と絞られます。そんな条件付きの実行が必要なテストを行う際に「XCTSkip」が活躍します。
中の実装は「こちら」をご参照ください。
なぜ「スキップ」があると良いのか?
以前まで(Xcode11.4より前)は下記の2択しかありませんでした。
- テストを合格にする
- テストを不合格にする
もし一部の条件下では必ずテストが成功するようにしていた場合、検証に合格していないプログラムが機能するということになりますし、テスト失敗とした場合は何が悪いのかの判断ができず無駄に時間を消費してしまいます。
XCTSkipを利用することでResult Bundlesを見た際にテスト結果のより詳細な情報がわかるようになりテスト全体の把握が容易になります。
Xcode11よりResult Bundlesへのデータの集約方法も変更されたのですが、そこら辺の詳細に関しては別の機会に記事を書きたいと思います。
使い方
使い方を紹介するために簡単なサンプルを作成しました。
テキストを音声で読み上げるとてもシンプルなものです(あまり良い例が思い付かず優しい目で見てください)import AVFoundation class Speech { private var nonMaleJPVoices: [AVSpeechSynthesisVoice] { return AVSpeechSynthesisVoice.speechVoices() .filter { $0.language == "ja-JP" && $0.gender != .male } } private func letsSpeaking() { let synthesizer = AVSpeechSynthesizer() let utterance = AVSpeechUtterance(string:"こんにちは") utterance.voice = nonMaleJPVoices.first synthesizer.speak(utterance) } }
letsSpeaking()
をコールすると「こんにちは」と音声が発せられます。
nonMaleJPVoices
では使用可能な音声オブジェクトのうち「言語が日本語」かつ「男性以外」の音声情報を渡す実装になっています。今回は
nonMaleJPVoices
の正当性をテストしてみたいと思います。
nonMaleJPVoices
の要件は以下の2つです。
- 言語が日本語
- 男性以外
実際に書いたテストは下記です。
class SpeechTests: XCTestCase { func testNonMaleJPVoicesContainOnlyJapaneseLanguage() throws { XCTAssertFalse(Speech().nonMaleJPVoices.contains{ $0.language != "ja-JP" }, "nonMaleJPVoices must not contain any language other than Japanese.") } func testNonMaleJPVoicesContainOnlyNonMaleGender() throws { XCTAssertFalse(Speech().nonMaleJPVoices.contains{ $0.gender == .male }, "nonMaleJPVoices must not contain a male voice.") } }上から順に
nonMaleJPVoices
は言語が日本語の要素を持つAVSpeechSynthesisVoice
の配列であることnonMaleJPVoices
は音声の性別が男性以外の要素を持つAVSpeechSynthesisVoice
の配列であることを確かめるためのテストです。
良さそうに見えるのですが、一つ注意が必要です。
AVSpeechSynthesisVoiceGender
はiOS13より追加されたプロパティなのでそれより前のOSバージョンでは取得ができません。
iOS12ではgender
へのアクセスができないのです。その場合テストはどうなるでしょう?
まず、機能の実装にはOSバージョンの条件分岐が入ります。
internal var nonMaleJPVoices: [AVSpeechSynthesisVoice] { if #available(iOS 13.0, *) { return AVSpeechSynthesisVoice.speechVoices() .filter { $0.language == "ja-JP" && $0.gender != .male } } return AVSpeechSynthesisVoice.speechVoices() .filter { $0.language == "ja-JP" } }すると
男性以外
という条件を含むのはiOS13以上
となります。先ほどのテストに戻りますがこのままではテストとしては不十分なので修正をする必要があります。
class SpeechTests: XCTestCase { /// 修正が必要 func testNonMaleJPVoicesContainOnlyNonMaleGender() throws { XCTAssertFalse(Speech().nonMaleJPVoices.contains{ $0.gender == .male }, "nonMaleJPVoices must not contain a male voice.") } }どのように修正するのがよいでしょうか?
iOS13未満では必ずテストが成功するようにしますか?ここで活躍するのがXCTSkipです。
性別に関してテストすべきなのは
iOS13以上の時だけ
でありそれより下のOSではテスト不要なのでスキップするのが適切です。早速修正しましょう!
class SpeechTests: XCTestCase { func testNonMaleJPVoicesContainOnlyNonMaleGender() throws { guard #available(iOS 13.0, *) else { throw XCTSkip("AVSpeechSynthesisVoiceGender tests can only run on iOS 13.0+") } XCTAssertFalse(Speech().nonMaleJPVoices.contains{ $0.gender == .male }, "nonMaleJPVoices must not contain a male voice.") } }実際にiOS12系の端末でテストを実行してみるとこうなります。
何やら見慣れないマークが表示されていますがこれがスキップしたことを示すマークです。Report Navigatorよりスキップの詳細を見ることができます。
使い方はとても簡単ですね...!
スキップの種類
XCTSkipを開始する関数は2種類あります。
XCTSkipIf(::file:line:)
条件式が真の場合にスキップします。
func testExample() throws try XCTSkipIf(UIDevice.current.userInterfaceIdiom == .pad, "this tests are not for iPad only") // test for other than iPad ... }XCTSkipUnless(::file:line:)
条件式が偽の場合にスキップします。
func testExample() throws try XCTSkipUnless(UIDevice.current.userInterfaceIdiom == .pad, "this tests are for iPad only") // test for iPad only... }XCTSkip
先に関数は2種類と説明しましたが、XCTSkip構造体を直接投げることも可能です。
その場合はガードと組み合わせる使い方がおすすめでWWDC20の「XCTSkip your tests」のセッションでも同じように紹介されていました。
func testNonMaleJPVoicesContainOnlyJapaneseLanguage() throws { guard #available(iOS 13.0, *) else { throw XCTSkip("this tests can only run on iOS 13.0+") } // test for iOS13+ ... }まとめ
テストを書いていく中で特定の条件下では実行できないテストというのが必ずあると思います(特に統合テスト)
そんなときにXCTSkipを使うことでテストの実行結果をより正確にモデル化することが可能となります。
テストの結果についてより具体的に詳細を把握するためにもぜひスキップしてみてはいかがでしょうか!!
- 投稿日:2020-09-20T08:29:39+09:00
【Swift】循環参照 丸わかり?
循環参照
循環参照とは?
お互いのインスタンスを参照しあい、メモリが解放されない現象。
「解放」...もうここ使わないから、あとはご自由にどうぞ、というイメージ。?なぜNG?
メモリ リーク
を引き起こす。
最終的にメモリが足りなくなり、アプリが落ちてしまう。メモリ リーク
メモリの解放忘れが原因で、永久にメモリが消費され続けること。
再現性が低く 見つけるのが困難で、悪質なバグの一つ。循環参照 を 防ぐには?
弱参照
をする。
weak
とunowned
を使う。(-> unknowned ではない...!)unowned: 所有されていない
unknown: 知られていない、不明な
unknowned -> こんな言葉ないなぜ防げるのか
弱参照を行うと、参照カウントは変わらないため。
weak
は「このインスタンスへの参照は、カウントしないよ」
という制限を、メモリ管理機能(= Automatic Reference Counting) に伝える。参照カウント
「プロパティや変数、定数からの インスタンスへの参照」が いくつあるかをカウントするもの。
参照の種類
- 強参照:
strong
-> デフォルト- 弱参照:
weak
- 非所有参照:
unowned
強参照
されたインスタンスは、参照カウントが 1 増やされます。
弱参照
・非所有参照
を行うと、参照カウントは変わりません。weak と unowned の違い
インスタンスが破棄された場合、弱参照(= weak) 元には
nil
が代入されます。非所有参照(= unowned) では、変数に
nil
が代入されません。
( -> インスタンス解放後に変数にアクセスすると エラー)改めまして、「循環参照」とは??
循環参照とは、インスタンス間でお互いを強参照しあった場合に参照カウントが0にならず、メモリ上にインスタンスが残り続けてしまう状態のこと。
永久にメモリが消費され続ける、「メモリリーク」という現象を引き起こす恐れがある。
それを防ぐために、
weak
やunowned
を使用して弱参照
を行う。おしまい。
- 投稿日:2020-09-20T01:57:34+09:00
【Swift】AudioKitを使ってみた(2020.9)
はじめに
【2020.9.21】 Oscillators and the Physics of Sound に書き漏れがあったので追記しました。
サウンドファイルの再生じゃなくて、音そのものを発信(発振?)させるのってどうすればいいんだろうとググっていて、AudioKitというライブラリを見つけました。
で、AudioKit Tutorial: Getting Startedというチュートリアルが、順を追って丁寧に解説されてるので動かしてみました。
ただページそのものがかなり古い(2016/バージョンは3.6)ので、公式ページにある最新版のAudioKit Playgrounds (zip)(バージョンは4.9.5)で動かしてみたときの変更点を備忘録としてまとめておきます。DLはこちらから。
実行環境
- Xcode 11.6
- macOS Catalina(10.15.6)
- 公式ページのAudioKit Playgrounds (zip)(バージョンは4.9.5)
Getting Started
まず AudioKit Playgrounds (zip)は最新版を使うので、チュートリアルページのリンクではなく、公式サイトのDLページから入手します。ファイル名は「AudioKitPlaygrounds-4.9.5.zip」になります。
これを解凍してXcodeで開いた後に・・・
Click the + button in the bottom left-hand corner of the Navigator view. Select the New Playground… option, name it Journey, and save it in the Playgrounds folder the other playground files are stored in.
ナビゲータービューの左下隅にある+ボタンをクリックします。 [新しいプレイグラウンド…]オプションを選択し、「ジャーニー」という名前を付けて、他のプレイグラウンドファイルが格納されているプレイグラウンドフォルダに保存します。
と書いてありますが、ナビゲータービューの左下隅にある+ボタンでは「New Playground…」なんて出てこないので、ナビゲータービュー上で右クリックすると「New Playground Page」が出てきますのでここから追加できます。
Xcodeのバージョンの問題かしらん?Playgroundってあんまり使ってないんで。。。さらに以下のような注釈がありますが・・・
This project will fail unless you build the project at least once using Product / Build, or ⌘-B. Once built, run the playground again and you’ll hear your playground emit 10 seconds of a beeping sound. You can use the Play/Stop button at the bottom left of the playground window within the Debug Area to stop or repeat the playground.
このプロジェクトは、Product / Buildまたは⌘-Bを使用してプロジェクトを少なくとも1回ビルドしない限り失敗します。 作成したら、遊び場をもう一度実行すると、遊び場から10秒間のビープ音が聞こえます。 デバッグ領域内のプレイグラウンドウィンドウの左下にある[再生/停止]ボタンを使用して、プレイグラウンドを停止または繰り返します。
Note: If the playground fails to execute, and you see errors in the Debug Area, try restarting Xcode. Unfortunately, using playgrounds in combination with frameworks can be a little error-prone and unpredictable. :[
注:プレイグラウンドの実行に失敗し、デバッグ領域にエラーが表示された場合は、Xcodeを再起動してみてください。 残念ながら、フレームワークと組み合わせてプレイグラウンドを使用すると、エラーが発生しやすくなり、予測できなくなります。 :[
私の環境でも結構出たので、新規のPlaygoundファイルを作ったら「⌘-B」を押し、実行してエラーが出たときは、Xcodeを再起動したり、AudioKitPlaygrounds.xcodeprojに既に作成済みのPlaygroudファイルを実行してから、再度自分で書いたPlaygroundを実行したりしてました。
Oscillators and the Physics of Sound
このコードをそのまま実行すると、以下のエラーが出ます。
error: 02Oscillators.xcplaygroundpage:21:1: error: use of unresolved identifier 'AKPlaygroundLoop' AKPlaygroundLoop(every: 0.5) { ^~~~~~~~~~~~~~~~最新バージョンでは、AudioKitとAudioKitUI(おそらくUI系)と二つのフレームワークに分割されていて、'AKPlaygroundLoop'は AudioKitUI にあるので、
import AudioKitUIを追加すればOKです。以降、'AKPlaygroundLoop'が出てくる箇所ではimportを忘れずに。
【参考】AudioKit/AudioKit/iOS/AudioKit/User Interface/AKPlaygroundLoop.swift
【2020.9.21追記】
rampTimeもエラーになります。
error: 02Oscillators.xcplaygroundpage:18:12: error: value of type 'AKOscillator' has no member 'rampTime' oscillator.rampTime = 0.2 ~~~~~~~~~~ ^~~~~~~~これは rampDuration に変更されていうようなので、以下のように変更します。
//---rampTimeは、rampDurationに変更 oscillator.rampDuration = 0.2【参考】AudioKit Reference AKOscillator Class Reference
Sound Envelopes
import AudioKitUIを追加すればOKです。
Additive Sound Synthesis
1.まず以下を追加。
import AudioKitUI2.Live ViewにUIを表示するので、Live Viewを表示する必要があります。「Alt+Cmd+Return」で表示/非表示を切り替えます。
【参考】How to create live playgrounds in Xcode
- AKPlaygroundView クラスを使ってUIを作成していますが、これがエラーになって動かない。
AudioKitPlaygrounds.xcodeprojに既存の他のファイルを見てみると、AKLiveViewController を使っているようなので、こちらで書き換えました。クラス名を含めた変更点は3つ。
・AKPlaygroundView >> AKLiveViewController
・override func setup() >> override func viewDidLoad()
・addSubview() >> addView()GitHubで、AudioKit/AudioKit/iOS/AudioKit/User Interface/を見ると、どちらのクラスも存在しているので AKPlaygroundView で何故ダメなのかは不明。
4.Live View にUIが表示されるようになるが、音が鳴らない。
オシレーターを生成するための「createAndStartOscillator()」という関数があって、サンプルコードでは生成時に「oscillator.start()」を実行しているけど、「AudioKit.start()」の後に実行しないと音が鳴らないようです。
なので、createAndStartOscillator()にある「oscillator.start()」をコメントにして、「AudioKit.start()」のあとに以下のコードを追加すればOK。
//AKOscillator.start()は、AudioKit.start()の後でないと音が鳴らない oscillators.forEach { $0.start() }Polyphony
1.まず以下を追加。
import AudioKitUI2.AKPlaygroundView を AKLiveViewController に変更。Additive Sound Synthesis の項を参照。
Sampling
コードの変更点は、特になし。ただサンプルコードで使っている.wavファイルは、自分でDL(リンクあり)して該当Playground配下の「Resources」フォルダに入れておく必要があります。
まとめ
AudoKit、面白そうだけど、入門的な記事は古いものしか見当たらなかったので、まとめてみました。参考になれば幸いです。自分で書いたコードではないので、あえてコード全文は載せていません。
他にいい参考記事あったら教えてください。
シンセサイザーの音声合成的な知識が必要なので使いこなすにはハードル高そうですが、画面のキャラクタタップしたら「どう森」みたいにインチキ言語を喋るとかさせたら面白いかも(笑)。