- 投稿日:2020-02-07T20:33:29+09:00
watchOSで〇〇アニメーション
watchOSアプリを開発した際に、いくつかアニメーションをつくりました
その中でうまくいったこと?いかなかったこと?があるので、そのまとめになります基本のローディングアニメーション
実装方法は以下の2つ
- パラパラ画像をつかう
- APNGをつかう
パラパラ画像をつかう
Appleのサンプルコード的にも正攻法といって良いでしょう
特徴としては、
- Asset Catalogを利用できるため、解像度の対応がしやすい
- 画像枚数が増えると管理が手間(あくまでAPNGにくらべて)
です
シンプルな Duration 指定の場合
// animatedImage: WKInterfaceImage animatedImage.setImage(UIImage(named: "Bus")) animatedImage.startAnimating()
startAnimating
はStoryboard上で設定されたDurationでアニメーションを行いますDuration + Repeat Count 指定の場合
animatedImage.setImage(UIImage(named: "Bus")) animatedImage.startAnimatingWithImages(in: NSMakeRange(0, 4), duration: 2.0, repeatCount: 3)APNGをつかう
APNGはアニメーションするPNG画像のことです。
特徴としては、
- リソースが1つになるので、画像パラパラよりも管理が楽
- 画像は、Extension ターゲットのリソースに入れる
- APNGの尺に合わせたDurationにすれば良い
- watchOSはAPNG対応のライブラリがない(*注)ので自前でソースコードを書く必要がある
*注:下書き時点ではなかったのですが、今ならSDWebImage/SDWebImageSwiftUIが使えるかもしれません
実装例については、Apple Watch で GIF/APNG を使う (ライブラリ不使用) が参考になりました(ありがとうございました)
こちらでスムーズにアニメーションができましたカウントダウンで遷移アニメーション?
やりたかったのは「3 -> 2 -> 1 -> 画面遷移」でした
前述の「パラパラ画像もしくはAPNGをつかい、画面側でタイマーセットをし一定時間後に画面遷移する」という実装を行いましたが、カウントダウンし切る前に遷移してしまったり・・・とうまくいきませんでした(こちらについて、シンプルで良い方法があればご教授いただけるとうれしいです?)
より動的なアニメーション
たとえば位置情報に基づいてアニメーションを移動・変更したい等のケースでは、Sprite Kit を使うことになると思います
ただし、watchOSで複雑なアニメーションをする際には、パフォーマンスに気を配るとよさそうです
(特にApple Watch Series 1などでは、最悪の場合、いつの間にかアプリがパージされます?)やるといいこと
スレッド管理
断然 ReactiveX/RxSwift の利用が楽です
- アニメーションの移動についての計算はバックグラウンド処理
- 描画処理はメインスレッドで実行
という実装にしましょう
SKTextureAtlas の利用
公式ドキュメントは About Texture Atlases
SKTextureAtlasの利用により、メモリ使用量、描画パフォーマンスが向上するようですまず、使用するテクスチャについては、Asset Catalog > + > New Sprite Atlas で専用フォルダをつくり、格納しましょう
テクスチャアトラスからテクスチャを作成
static let TextureAtlasName = "Sprite Atlasのフォルダ名" static let TextureAtlas = SKTextureAtlas(named: TextureAtlasName) lazy var textures: [SKTexture] = { var textures = [SKTexture]() let numberOfTextures = TextureAtlas.textureNames.count - 1 for index in 0...numberOfTextures { let name = String(format: "%@%d", TextureAtlasName, index) textures.append(TextureAtlas.textureNamed(name)) } return textures }()テクスチャの切替のみ(要はパラパラ)でアニメーションする場合は以下のような実装
func animate() { let node = SKSpriteNode(..省略..) // アニメーション大賞のSKSpriteNodeオブジェクト生成 let action = SKAction.animate(with: textures, timePerFrame: 0.03) let repeatAction = SKAction.repeatForever(action) node.run(repeatAction, withKey: key) // node: SKSpriteNode }画像比率の適用
Sprite Kitを使う際にはAutoLayoutやCore Graphicsのような簡単な配置ができません
そのため、全端末でうつくしく表示するためには、画像比率に対してテクスチャサイズの変更等が必要かもしれませんたとえば、背景画像を画面いっぱいに表示したい場合は以下のように SKScene のサイズを指定します
InterfaceController.swiftfunc setupScene() { let image: UIImage = BackgroundImage let size = contentFrame.size let portraitRatio = size.height / image.size.width let landscapeRatio = size.width / image.size.height let multiplier = min(portraitRatio, landscapeRatio) let sceneSize = CGSize( width: image.size.width * multiplier, height: image.size.height * multiplier) let scene = SKScene(size: sceneSize) scene.anchorPoint = CGPoint(x: 0.5, y: 0.5) scene.scaleMode = .aspectFit sceneInterface.presentScene(scene) }以降、このScene上で配置するNodeのサイズは、
multiplier
を使った計算が必要になるでしょうまとめ
watchOS6よりWatch-only appの開発が可能になりました。
まだアプリ数は少ないようですが、AppleWatch用のApp Storeもリリースされました。
これからwatchOSアプリ市場が盛り上がることを期待!以上です???
ありがとうございました?Thanks to
SpriteKit Animations and Texture Atlases in Swift
Apple Watch で GIF/APNG を使う (ライブラリ不使用)
WatchKit のカスタムUI実現方法のまとめ
- 投稿日:2020-02-07T14:25:12+09:00
Unity ARkitのFaceTrackingでシーン遷移するとクラッシュする
どんな問題か
UnityでFaceTrackingのアプリを作ったら起こった問題
FaceTrackingシーンから他のシーンに遷移するとき、IOS実機だと落ちるlibc++abi.dylib: terminating with uncaught exception of type Il2CppExceptionWrapper
(lldb)こんなのを残してさよなら
解決方法
ios - Unity Switch between ARKit Face Tracking and Rear Camera? - Stack Overflow
↑
これで治った。
ExampleのUnityARFaceAnchorManager.cs を改変した人は注意永遠悩んでた。海外質問フォームって偉大だなぁ、
- 投稿日:2020-02-07T08:14:48+09:00
CA.swift #11 ~3年後のアプリ設計を考えよう~ 参加報告
大変遅くなりましたが
2020年1月30日に開催されたCA.swiftへ
ブログ枠として参加させていただきました際の報告です。
https://cyberagent.connpass.com/event/155392/ざっと内容や感想を書かせていただきます。
Thinking about Architecture for SwiftUI
登壇者
@d_dateさん
スライド
https://speakerdeck.com/d_date/thinking-about-architecture-for-swiftui
内容
タイトルはSwiftUIの設計になっているけど
メインはDataflowの話(あと実は時間が30分だと思っていた)
宣言的にUIが記述できるフレームワークが流行っている
- SwiftUI
- Android: Jetpack Compose
- ReactNative/Flutter
SwiftUIとProperty Wrapper
@Stateなどで修飾されたプロパティと
ユーザーの操作をバインドして画面の状態を更新して再描画するという
Dataflowを構築している。DataflowといえばCombine
- 宣言的に非同期なイベントを型として表現できるSwiftのAPI
- 様々なオペレーターでイベントをハンドリングできる
- Apple製
RxSwiftに取って代わるみたいな流れになっている。
SwiftUIと組み合わせて使われることが多い
CombineのPublisherをViewでSubscribeして
値が流れてくると
画面の状態の更新や画面の再描画を行う。View with ObservedObjectを使った例
ObservableObjectプロトコルに適合したViewModelを
@ObservedObjectとしてViewで参照を保持して
SwiftUIのイベントとバインドさせて単方向のデータの流れ(Unidirectional Dataflow)
を構築する。
Unidirectional Dataflowといえば
- Flux
- Redux
- Composable Architecture
FluxとReduxについては設計についての良い本があるのでそちらまで
https://peaks.cc/books/iOS_architecture
Composable Architecture
pointfree.coで紹介。
- ReduxとElmアーキテクチャを組み合わせたもの
- SwiftUIとCombineに最適化(両方使ったアプリ作成を行っている)
- 関数型プログラミング
- View / State / Action / Store / Reducerを用いる
- 副作用はEffect型で全て定義
- 小さい部品を組み合わせて大きなデータフローを構築している
私も購読しているのですが
最初は仕組みがいまいちわからず
複数回見ないと全体の理解が難しかった印象を持っています。ただ
全てがパターン化している上に
宣言的に記述できるので
中身をわかっている人には可読性が非常に高いなと感じています。アプリの実装内容だけではなく
状態の変更を集約するという考えや
関数を型として扱う方法など
色々なことが学べるのでとても参考になると個人的には思ってます?簡単な流れ
- ActionをStoreに送る
- ReducerでActionをハンドリングしてStateを更新する
- Actionの結果Effect型で定義した副作用が発生する
- 更新されたStateを用いてViewを更新する
良さそうだけど、iOS13以降ではないと使えないし。。。UIKitとRxSwiftで同じことができないかやってみた
UIKit + RxSwift
- ユーザのアクションをSubscribeして流れてきた値をStoreに送る
- ReducerでActionをハンドリングする
- Effect型はiOSバージョン関係ないのでそのまま使え、Actionの結果Effect型で定義した副作用が発生する
- 更新されたStateを用いてViewを更新する
ただ一つのStore
Storeはアプリ全体で一つだけ。
理由として
- 認証情報などが引数で引き回す必要がなくなる
- 今後の情報の追加も楽
ただStoreが全てを管理していることで
- distinctUntilChangedしないと処理が何回も呼ばれてしまう
- 画面遷移時に初期化処理をしないと、前の画面の処理が動いてしまう
こともある(ここ何か聞き間違えていたかもしれません)。
SwiftUIとCombineで実現しているAppleの考えを
iOS13以前でも実現できることを具体的に知ることができて
大変勉強になりました。AbemaTVにおけるiOSアーキテクチャの課題解決
登壇者
@_yysskkさん
スライド
https://speakerdeck.com/yysskk/solving-problems-in-abematv-ios-architecture
内容
プロダクト背景
2015年3月から開発開始
現在は10名で開発チーム人数の変遷
4(2015)
↓
6(2017)
↓
14(2019)設計の変遷
Flux(第1世代)
↓
MVVM+Flux(第2世代) ← 縦化、ビデオ機能開始
↓
MVVM(Unio)+Flux(第3世代) ← アプリ内コイン、投げ銭機能開始Flux(第1世代)
設計の選定理由
- 複雑な状態管理をわかりやすくしたい
- クライアント間(Android/iOS/Web)で同じ設計にしたかった
Fluxについて
https://facebook.github.io/flux/docs/in-depth-overview大まかな処理の流れ
- ViewControllerがActionを呼ぶ
- ActionがAPI通信を行う
- APIから取得したデータをDispatcherに流す
- StoreでDispatcherから流れてくるイベントをbind
- ViewControllerがStoreの状態を監視してUIを更新
良い点
- View間の依存関係が減る
- 開発者の実装が統一されやすい
- データの流れがわかりやすい
MVVM+Flux(第2世代)
縦化とビデオ対応機能開始
第1世代のままだと困ること
- 機能の複雑化でStoreやUIの合成ロジックがViewControllerに増えた例
Storeの値が更新された時にリロードしていたものに加えて
縦にした画面サイズの変更時もリロードする必要が出てきたため
combineLatestしなければならなくなった。そこで
MVVMの導入
※
実際はRxを使用しているため
ViewModelではなくViewStreamという名前になっているViewModelのinitで
Inputのイベントを元にOutputを合成する良い点
- ViewControllerをUIイベントの伝播と状態をUIにbindするだけにできた
- プレゼンテーションロジックをUIから分離したので単体テストを書くのが楽になった
- グローバルで保持する必要のない画面の一時状態をUIのライフサイクルで破棄できる
MVVM(Unio)+Flux(第3世代)
コイン機能の開発、投げ銭機能の開発
->チームメンバーの数が増えた第2世代のままだと困ること
- ViewStreamの実装が実装者でバラバラ
例
テキスト検索を関数で定義するか
Observableのプロパティを使うか
PublishRelayを使うか
などそこで
Unioの誕生(ViewModelの構造を統一)
https://github.com/cats-oss/Unio良かった点
- ViewModelの実装の統一が実現
- ViewModelのロジックの流れが単一方向なので可読性が上がった
現在の課題
- 前世代の実装が残っている
- 第1世代の残っている実装でStore to Storeな実装があり処理が複雑になっている
- 画面の単体起動ができない
- Actionが直接Resourceを参照している
まとめ
変更を入れるタイミングは全機能の刷新や大きな機能開発が入る時に行う。
発生した課題に対して都度解決しながら変化していくことができた。AbemaTVは比較的新しいので
最初の設計からシンプルでわかりやすいなと感じました。変更に応じて設計を都度見直すというのも
変化の多い現在のアプリ開発ではとても自然な流れだと思っています。ただ
前世代の実装が残っているということもおっしゃっていたので
やはりずっと負債になって手が出せないような部分も結構あるんだろうなとも感じ取れました。そういったところに対して
どういう状態で手が出せずに
今後どうしていくのかといった点も聞いてみたいですね?Amebaの設計とこれから ~カオスからの脱却と再びカオスを生み出さない努力~
登壇者
スライド
https://speakerdeck.com/shunsakumiki/caswift-11
内容
2017年中途入社
カオスすぎた設計
2010年にリリースされて以来
10年以上を運営する中でたくさんの転換
- WebViewアプリからフルネイティブに
- Objective-CからSwiftに
- メンバーの入れ替わり
- 当時デファクトと呼ばれて今は古くなっている設計
- リアーキテクチャを試みようとしたが道半ばになっている痕跡
基本はMVC
俗にいうMassiveViewController
ViewControllerからAPI通信を行っているものが多いものの
それはよくないという風潮からHogeHogeManagerなど名前から役割がいまいちわからない
クラスが作られていることもある。テストはない。
なぜか一部VIPER
おそらくカオスなMVCから抜け出そうとして痕跡かもしれないが
ドキュメントがないのでいまいちわからない。VIPERでもテストはない。
このままだと
新規画面を実装するにしても
- どの設計にすればいいか毎回0から考えて大変
- 人によって異なる設計をする状態でレビューが大変
- 設計をしたエンジニアがいなくなると後から変更加えるときに調査が必要になったり負担が重くなりそう
既存の実装に手を加える場合
- 設計がぼんやり&密結合&テストがないので何が正しいのかがわからず、工数が通常よりもかかってしまう状態
なのでリアーキテクチャ
方針として
- 最終的にはMVVM+Flux
- bindingとして利用するためにRxSwiftの導入も進める
- テスタビリティも考慮する
- CI環境を整えて自動テストを回していく
- 設計に関してはチームみんなで考える
特に最後の設計をチームで考えるが大事なことで
これがないとリアーキテクチャのモチベーション維持が難しくなる。まずはMVVM
採用した理由として
- ロジックが複雑な画面がそこそこあった
- 画面間で同期が必要な仕様があまりなかった
bindingにはRxSwiftを利用
- 社内で使用しているプロジェクトが多かったため
初期のMVVM
ViewModelのinit内でPublishSubjectを生成して
ObserverとObservableのプロパティにセットして購読していた簡単な画面ならこれで困ることはない
しかし
- Input,Outputのインターフェイスの形を実装者に委ねていたためレビューコストが肥大
- 複雑な初期化処理が入ってinitが肥大してメンテナンスコストが爆増
Usecaseの導入
ViewModelのinitで行っていた下記の処理をUsecaseに移動
- Observableの加工
- API通信
- ModelからView表示用Modelへ変換するTranslatorの呼び出し
MVVMの改良
- Input,OutputをProtocolに切り出しインターフェイスを統一
- initで行われていた処理を責務ごとに分離して肥大化の防止+テスタビリティの向上 ※ 2つ目に関しては Usecaseに切り出したことで肥大化を防いだのか また別で責務の分離を行ったのかは 確認できませんでした??♂️
Flux導入
仕様変更によりMVVMの仕組みだと煩雑になってしまうようになった
例えば
- ユーザーのログイン、ログアウト状態によってアプリ全体の状態を変更
- あるタブの画面上の値の更新を別のタブの画面でも受け取らなければいけない など
最初はObserverとObservableを持つ
Singletonのオブジェクトを利用して解決しかし
Singletonで何でもできてしまうという点や
さらに監視する項目が増えた時のスケーラビリティが良くないと感じる点から
Fluxを導入使い方は
- データフローはFacebookのものと同様
- StoreとViewModelを直接bindさせることで非Rx依存に(ExtensionでStoreをObservableに変換)
効果
- 利用者側は必要なイベントやStateを持つStoreを見ればよくなり、余計なObservableの購読がなくなった
- Singletonのときに感じていた処理の肥大化がする感じがしなくなった
- データフローが単方向でAPI通信が発生する処理でもキレイな構成を保てた
でも注意点も
利用箇所を考えずに入れてしまうと簡単な画面だとむしろ煩雑になってしまう可能性がある
使い所
MVVMではキレイに作れない処理の流れがあるような時に選択肢として利用
登壇者個人としては
NotificationCenterやObserverパターンで毎回独自の便利クラスを作るよりは
断然Fluxを使った方が良いと考えている。現在までの結果(良かった点)
- 新規画面の実装は設計がある程度統一されているのでレビューが楽
- チームで認識を合わせて進めてきたので設計を考える大切さの共通認識が生まれた
- 設計ドキュメントを社内に残せるようになった
- テストを考慮したことでCI環境の見直しができた(メンテナー属人化したJenkinsからBitrise)
現在までの結果(悪かった点)
- 試行錯誤しながらだったため必要のない負債も生んでしまった
- もう少し検討する時間が必要だった
- 全画面でリアーキテクチャするまでのマイルストーンがまだ引けていない
これから
不安なこと
- ViewModelの先にあるUsecaseやRepositoryの作りをどうするか
- もし現メンバーがいなくなったらまた同じカオスを生み出してしまうのではないか
Layered Architectureの考え方を導入したい
しかし
人によってLayered Architectureの考え方が異なるので
Amebaに取り入れるにはどうしたら理想かを考えていきたい。Layered Architectureとは?
https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch01.htmlまとめ
長くサービスを運営しているとカオスは生まれてしまうものの
この状況を伸びしろだとチームで捉えることができればどんどんリアーキテクチャを進めていった方が良いと思った。
設計に銀の弾丸はないので新しいものでもサービスの特性にマッチすればどんどん取り入れていきたい。
大事なのはチーム全体で設計へのコミットをしていくこと。聞いていると
色々設計パターンが混ざっていて
コードを理解するのが大変そうだなと思いました。そんな中で
どのように現在の動作を保証しながら行っているのか?
や
どのくらいの期間でどこまで達成できているのか?
といった話もぜひ聞いてみたいですね。完全に達成するまでの道のりは険しそうですが
ここからどう変化しどこまで達成できたのかの次回の報告が楽しみですね?5年目に突入したAWAのアプリ設計
登壇者
スライド
https://speakerdeck.com/jinsasaki/awa-caswift-11
内容
現在
v2.0
iOS9までサポート
iOSエンジニア3名History
Objective-CからSwiftへ
開発体制の変更で人数など色々あったがv1.0 -> v2.0で
フルスクラッチ開発プロダクトの特性
- オフラインでも利用できる・再生できるようにするためにキャッシュが必要
- プレイヤーはどの画面からでもアクセスできる
など
v1の設計
MVCでRealmを利用。
問題点
- 2000~3000行のMassiveViewController
- Viewがかなり状態を持っている
- Controllerの責務が巨大
- Entityがロジックを持っている
- 万能なManager
- 神Util
- 全ての層でRealmに依存
v2でフルスクラッチ開発
背景
これまでの機能を全て見直し
全画面に手を入れる必要があったことから
作り直す良い機会だと捉えたまっさらな状態から設計を考えることができた。
目標
- 責務の分離
- 状態の一元管理
- Realmへの依存からの脱却
- Reactive Programming
検討結果
Flux(with RxSwift) + レイヤードアーキテクチャー
やってみた結果
新規開発はやすくなったが
v1とv2の同時並行開発していたのでだいぶ大変だった。。。
加えていつ終わるのかが見えないので
モチベーションの維持が難しい。Apple Watchにも対応
watchOS6.0以降対応ということで
MVVM with SwiftUI + Combine
で開発。
開発してみた結果
- まだまだ使えないライブラリが多い(XCTestやFirebaseなど)
- バイナリのサイズが大きくなるとアプリの転送速度がかなり遅い
- watchOSとSwiftUI起因のバグ(Betaだったからかもしれない)
これからの目標
- ViewControllerに状態やロジックを持っているものがあるのでそれを分離したい
- iOS/Android/PCで共通に利用できる共通の設計を導入する
- テストをもっとやりやすくする
v1とv2を同時に開発していたとおっしゃっていましたが
どっちの実装をしていたのか混乱しないのかなと
タスクやスケジュールの管理方法なども気になりました。長年運用してきたアプリなので
仕様がいまいちわからない部分もあるのかなと思い
v1と同じ動作が期待される機能を
v2ではどうやって動作の保証をしていったのかなどの
話も聞いてみたいですね。ディスカッション
自分でまとめようと思いましたが
とても良いまとめ記事がありましたので
そちらのリンクを貼らせていただきます??♂️https://note.com/fromkk/n/n986d20a31708
最後に
大規模なアプリを長年運用していくにあたり
どのような状況でどういう判断をしていったのかが
具体的に伝わってくる内容ばかりで
自分がこういう状況にあったらどうしていただろうと
あれこれ考えながら楽しく聞くことができました。そして
機能の変更や追加
人員の入れ替えなどがある中で
どうやって設計を保ち
どのようによりゴールに近づいていくのか
そういった部分への取り組みについても
聞いてみたいですね。また
半年、1年後といった経過の報告を
聞く機会がありましたら
ぜひ参加したいなと思います。運営のみなさま
登壇されたみなさま
素敵な会をありがとうございました?
- 投稿日:2020-02-07T07:28:30+09:00
iOSシミュレータにプッシュ通知を送ってみる
※本記事は一般に公開されている範囲で書いています。スクリーンショットの添付は自粛します
Xcode 11.4 からiOSシミュレータがプッシュ通知のシミュレーションをサポートしますね。
Simulator supports simulating remote push notifications, including background content fetch notifications.
Xcode 11.4 Beta Release Notesシミュレータでプッシュ通知をシミュレーションする方法は2つありますが、両方とも有効な Apple Push Notification Service payload ファイルが必要になります(拡張子は .apns である必要があります)。
{ "aps":{ "alert":"Test", "sound":"default", "badge":1 } }方法1:apnsファイルをシミュレータにドラッグアンドドロップする
この場合はJSONのトップレベルに
Simulator Target Bundle
を追加し、アプリの bundle identifier を含める必要があります。{ "Simulator Target Bundle": "YOUR_APP_BUNDLE_ID", "aps":{ "alert":"Test", "sound":"default", "badge":1 } }方法2:コマンドラインから送る
simctl
を使う方法もあります。この場合Simulator Target Bundle
は不要です。$ xcrun simctl push <SIMULATOR_DEVICE_ID> <YOUR_APP_BUNDLE_ID> <APNS_FILE_NAME>例:
$ xcrun simctl push A0AF405F-FE73-45DA-8D7D-F1FE37821992 com.example.my-app test.apns
SIMULATOR_DEVICE_ID
は次のコマンドで調べることができます。xcrun simctl list注意点
- この機能を試すためには、アプリがプッシュ通知に対応しており、かつ、ユーザーが通知を許可している必要があります
- この機能はあくまで シミュレーション なので、APNSを介したプッシュ通知のテストは別途実施したほうが良いでしょう
参考リンク
- 投稿日:2020-02-07T02:03:34+09:00
XcodeでiOSアプリを作成中にiOSのバージョンをアップしたらエラがー出た話
※2020年1月29日時点の情報になります。記事投稿日時点の環境ではエラーは発生していません。開発中にむやみやたらと新しいものに飛びつくと良くないよという自身の忘備録として、また同じような状況に今後陥った方へ向けて書いています。
先日Xcode、iOS13.3のiPhone実機で開発をしていた際にiOS13.3.1にバージョンアップするとエラーが発生し、対応に困ったため記事にします。この手の文章を書き慣れていないため、練習も兼ねて・・・
結論
iOSのバージョンを13.3に戻すと解決しました。知識がない状態で開発中に環境いじるのは良くないですね。
経緯
環境
・macOS Catalina 10.15.2
・iOS:13.3 実機:iPhone11
・Xcode 11.3.1
.Apple Developer無料アカウント上記環境にてiPhone実機で動作確認をしながらiOSアプリを開発していました。
ここで新しいもの好きの私は
iOS13.3.1のアップデートが来た!更新!
↓
macOS10.15.3も来た!更新!
↓
macOS更新したらXcodeでも何か更新してる・・・(ここあやふやです)環境を一気に更新し、数時間後に実機ビルドをかけ新しく作成した機能の動作確認しようとすると・・・
このようなエラーが出ました。
手元に他にアプリは無く、Apple Developer無料枠は1つの端末に3個
まで同時に利用できるという認識なので見に覚えがない。という状況でした(調べてXcodeの設定を色々いじったりしましたが、解決策は見つかりませんでした)原因として真っ先に考えられるのが各種バージョンアップ(Xcodeは何か更新した?)による可能性が高かったため、元のバージョンにすること。
やったこと
Xcode→iOS→macOS(面倒くさい、できればやりたくない・・・)の順でバージョンを戻すことに。
※ダウングレード、アップグレード等は自己責任の範囲で行ってください。Xcodeを再インストール → 変化見られず
iOS → ヒット。エラーが解消しました。iOSのダウングレードですが、詳しく解説しているサイトが多数ありますので詳細はそちらに譲ります("iOS ダウングレード"で検索すれば引っかかります)
私はmacにiOS、iPadOSなどのIPSWをダウンロードできるサイトからiOS13.3をダウンロードし、Finder経由でiPhoneにインストールする形でダウングレードを実施。
再度実機ビルドをするとエラーは発生しなくなり、元通りになりました。最後に
それから4、5日経ちアプリの開発に一区切りしたため、再度iOSを13.3.1に更新して試して見るとエラーは出なくなっていました。
配布後、即アップデートしたのが問題だったのか、他に原因がありiOSを戻すことで"たまたま"解決できたのかという点で少しもやもやしています。