20220115のSwiftに関する記事は4件です。

【iOS × アーキテクチャ】iOSにおける、GUI/システムアーキテクチャとは?

目的 GUIアーキテクチャ システムアーキテクチャ についてまとめること 流れ そもそも、アーキテクチャ とは? GUIアーキテクチャ の例 GUIアーキテクチャ とは? システムアーキテクチャ の例 システムアーキテクチャ とは? モバイルアプリ開発における問題点 5を解決するアーキテクチャ 0. そもそも、アーキテクチャ とは? アプリケーションを開発する上で、開発者同士の共通認識を行うためのもの 開発者同士の共通認識とは? → 3つある ① : クラスなどの要素の関係性整理 ② : 伝達順序の整理 ③ : 開発の規則性 根幹にあるものは? Presentation Domain Separation : プレゼンテーション領域の分離 という考え。 「システム本来の関心領域(ドメイン)を、UI(プレゼンテーション)から引き離す」 ということ。 プレゼンテーション( =View ), ドメイン( =Model ) を分けて考えましょうね。 というもの。 ※ プレゼンテーション と ドメイン については、下の補足にて説明があります。 種類(iOSの場合) 一般的にiOSアプリのアーキテクチャと呼ばれているものには、2種類存在する。 GUIアーキテクチャ と システムアーキテクチャ だ。 次の章からは、GUI/システムアーキテクチャについて、採用されているアーキテクチャの例をだしながら説明していく。 (それぞれのアーキテクチャについての説明は、また後日...) 補足 ■ プレゼンテーション・ドメイン とは? プレゼンテーション ( =View ): 「UIに関係するロジック, ユーザーが操作する画面」 どのようにレイアウトを行い、情報を装飾するか を考えている ドメイン ( =Model ): 「アプリケーションのユーザーが思い描く、"システム本来の関心領域"」 情報をどのようにモデリングし処理するか を考えている ■ プレゼンテーション と ドメイン を分けるメリット ・役割が分かれているため、理解しやすい ・それぞれを一つのオブジェクトとして扱えるため、コードの重複を防げる ・複数人での開発で、分業がしやすい ・テストコードが書きやすい 1. GUIアーキテクチャ の例 GUIアーキテクチャには以下のアーキテクチャが含まれる。 MVC :Model-View-Controller Presentation Model パターン (MVC+Presentation Model) MVVM :Model-View-ViewModel MVP :Model-View-Presenter Flux 2. GUIアーキテクチャとは Viewからの視点で、PDSを実践するため際の具体的なレイヤー構造をパターンとして示したもの。 GUIアーキテクチャの "欠点" 「UIか、それ以外か」 という分け方しかできないこと GUIアーキテクチャにおいて、「Model=UIに関係しない処理全て」となってしまう しかし、UIに関係しない処理 の中にも様々な種類が存在する。それを分けることなく、Modelという1つにまとめて考えるのは危険。 以下の2つは、本来 プレゼンテーション・ドメイン どちらにも当てはまらない。しかし、GUIアーキテクチャでは、「ドメイン( =Model )としてひとまとめにされる」 → 役割ごとに分類を行えていない ①:サーバ API からのデータ取得を試 み、そこで発生したネットワークエラーをハンドリングする ②:データをストレージに永続化する」 3. システムアーキテクチャ の例 システムアーキテクチャには以下のアーキテクチャが含まれる。 レイヤードアーキテクチャ Hexagonal Architecture Onion Architecture Clean Architecture 4. システムアーキテクチャ とは? "GUI"アーキテクチャの汎用性を増したもの さらに詳しくいうと、"システム"アーキテクチャは、"GUI"アーキテクチャよりも広い、UIという単位にとらわれることなくシステム全体の構造を示せるもの。 「システムアーキテクチャ > GUIアーキテクチャ」 なぜそう言えるのか? GUIでは行っていない、ドメインの先をどのように分けるのか ということを考えているから。 GUIアーキテクチャは、プレゼンテーションとドメインを分けて考える。 しかし、ここでのドメインとはUIに関係しない処理全てとなる。 「情報をどのようにモデリングし処理するか」を考えているドメイン が、このような曖昧な定義では開発を行う上で、開発者同士の混乱を招きかねない。 そこで、システムアーキテクチャでは、GUIアーキテクチャでは考えない、「ドメインの先でどのようにレイヤーを切り分けるべきか」や「システム全体をどのように接合すべきか」といったものを考える。 5. モバイルアプリ開発における問題点 モバイルアプリ開発における問題点は、「画面遷移」です。 1〜4 では、GUI/システムアーキテクチャについて説明を行った。 しかし、「モバイルアプリ開発においては重要であるにも関わらずどちらのアーキテクチャでもヒントを与えてくれない関心事」があります。 それが 画面遷移 です。 モバイルアプリは、Webアプリ と違い、UIコンポーネントが大きい。操作を指で行うためです。 一画面に多くの情報を載せることが難しく、画面遷移を繰り返すことで快適なユーザー体験を実現した。 しかし、「多くの画面遷移をどう設計するのか」は既存のアーキテクチャでは対処できない問題となっています。 次の章では、それを解決するためのアーキテクチャをいくつか示します。 6. 5を解決するアーキテクチャ Coordinatorパターン と MVVM-C Routerパターン と VIPER Micro View Contrller 参考文献 『iOSアプリ設計パターン』 (電子版: 税込 3200円)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SwiftUI】secureFieldの枠線を下線にしてみた

本日は、SwiftUI の 1.secureFieldの書き方 2.secureFielsの枠線スタイルを下線に変更 の2点についてお話しします。 実行環境 1.Swift praygrounds バージョン4.0 (1567.22) 2.SwiftUI (XcodeバージョンVersion 13.2.1でも動くことを確認) secureFieldの基本的な書き方 コード例 secureFieldview1 import SwiftUI import PlaygroundSupport struct ContentView: View { @State var password1 = "" @State var password2 = "" var body: some View { VStack { SecureField ("パスワードを入力1", text: $password1, onCommit:{}) .textFieldStyle(PlainTextFieldStyle()) .font(.system(size: 20)) .padding(.all) SecureField ("パスワードを入力2", text: $password2, onCommit:{}) .textFieldStyle(RoundedBorderTextFieldStyle()) .font(.system(size: 20)) .padding(.all) } } } コード説明 secureField 第一引数は、テキストフィールド内に表示する文字 第二引数は、@Stateで宣言したString型の変数を宣言 (@Stateじゃないと中身が書き換えられないのでエラーになるという認識) 第3引数には、入力が完了した(returnがタップされた)タイミングで行いたい処理を クロージャーで指定 (ここは自分は全くわからなかったので違うサイトの説明をそのまま引用しました。) .textFieldStyle(PlainTextFieldStyle()) ここでは、PlainTextFieldStyleで枠線なしスタイルを指定 .textFieldStyle(RoundedBorderTextFieldStyle()) ここでは、RoundedBorderTextFieldStyleで枠線スタイルを指定 実行結果 secureFieldのスタイルを下線に コード例 import SwiftUI import PlaygroundSupport struct ContentView: View { @State var password3 = "" var body: some View { VStack { SecureField ("パスワードを入力3", text: $password3, onCommit:{}) .textFieldStyle(PlainTextFieldStyle()) .font(.system(size: 20)) .padding(.all) Divider() .padding(.horizontal) } } } コード説明 secureFiled自体に下線スタイルは存在しません。 そのため、枠線なしスタイル選択し自分で下線を引く必要があります。 そのため secureFieldのtextFieldStyleは 枠線なしスタイルのPlainTextFieldStyleを使います。 その上で今回は Divider() を使用します。 Dividerは区切り線を引いてくれます。 そのためPaddingでうまく長さを調整してあげて、 VStack内でDividerを使えば 以下の実行結果のように下線スタイルにすることができます。 実行結果 他にうまい下線スタイルにする方法があればコメントで教えてください。 コードや説明などの指摘もお願いいたします。 参考記事 【SwiftUI】SecureFieldでパスワード表示の入力欄を実装する方法を解説 SwiftUIで区切り線を引く方法【Divider】
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SwiftUIで画面遷移を実装する

環境 Xcode13.2.1 Swift 5.5.2 基本的な画面遷移方法 1. NavigationLink 2. sheet 3. フラグによるViewの切り替え 1. NavigationLink NavigationLinkはiOSの基本的なpush遷移になります。 以下のように実装します。 NavigationLink(destination: 遷移先のView) { 任意のView(このViewをタップすると遷移先に指定したViewに遷移する) } 実装例 Viewのタップで遷移する方法 NavigationLinkの末尾のクロージャに追加したViewをタップすることで遷移するやり方です。 追加したViewは最初からタップ可能になっています。 struct ContentView: View { var body: some View { NavigationView { NavigationLink(destination: SecondView()) { Text("画面遷移") } } } } 遷移元 遷移先 NavigationLinkはNavigationView内に書いていないと画面遷移がされないので注意してください List表示でNavigationLinkを実装したい場合は以下のようにできます。 NavigationView { List { ForEach(users) { user in NavigationLink(destination: UserInfoView(user: user)) { Text(user.name) } } } } isActiveで遷移を判定する方法 Viewを追加して遷移させる以外にも、NavigationLinkにはisActiveという引数を持っており、この値がtrueになった時に画面遷移が実行されます。 以下のコードは、ボタンをタップした時にState変数のshouldShowSecondViewをtrueにしています。 NavigationLinkのクロージャをEmptyView()とすることで、上記で説明していたようなタップで遷移させるためのViewは何も表示されません。 こちらの遷移方法は、何か処理が完了した後に画面遷移させたい場合などに使うことが多い思います。 struct ContentView: View { @State private var shouldShowSecondView: Bool = false var body: some View { NavigationView { VStack { NavigationLink(destination: SecondView(), isActive: $shouldShowSecondView) { EmptyView() } Button { shouldShowSecondView = true } label: { Text("フラグ切替") } } } } } 遷移元に戻る方法 NavigationLinkでの画面遷移は自動的に遷移先に戻るボタンが表示されます。 戻るボタンを使わないコードでの実装は、環境変数dismissを使用します。 struct SecondView: View { @Environment(\.dismiss) var dismiss var body: some View { Button { // 任意の場所で呼ぶ dismiss() } label: { Text("シートを閉じる") } } } 2. sheet sheetは下からViewが表示されるモーダル表示です。 .sheet(isPresented: Binding<Bool>), onDismiss: (() -> Void)? = nil) { 遷移先のView } 引数 isPresented ここに指定した変数がtrueの時に遷移先のViewがモーダル表示されます。 onDismiss シートが閉じる時に実行されるクロージャです。何も処理がない場合は定義する必要はありません 実装例 struct ContentView: View { // 表示フラグ @State private var isShowingView: Bool = false var body: some View { Button { isShowingView.toggle() } label: { Text("シート") } .sheet(isPresented: $isShowingView) { SecondView() } } } 遷移元 遷移先 Buttonにsheetを定義して、タップ処理にisPresentedのフラグを変更する処理を実装しています。 このようにすることでボタンが押された時にtrueになるのでシートが表示されるようになります。 表示フラグに使用する変数は、値の変更を監視できるように@Stateを付けた変数である必要があります。そのため引数のisPresentedに定義する際は$を付与します。 @State private var isShowingView: Bool = false 遷移元に戻る方法 下にスワイプしてシートを閉じる dismissハンドラーを実行する dismissハンドラーはNavigationLinkの戻る実装と同じになります。 3. フラグによるViewの切り替え NavigationLinkなどの画面遷移メソッドは使わずにフラグを用いてViewを出し分ける方法です。 瞬時にViewが表示されるので、アニメーションを付けたい場合は別途実装する必要があります。 実装例 struct ContentView: View { @State private var isShowingView: Bool = false var body: some View { if isShowingView { SecondView() } else { Button { isShowingView.toggle() } label: { Text("フラグ切替") } } } } 今回はSwiftUIの基本的な画面遷移方法についてまとめました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【RealityKit2】Object Captureを試してみよう!

はじめに iOSデベロッパーがObject Captureを試してみました。 ARはやっぱり面白い!と思いましたので、 まずはこの記事を見てとりあえずやってみるか、と思って頂ければ幸いです。 環境 Xcode Version 13.2.1 (13C100) Swift5(コーディングしてないので関係ないですが一応) Mac OS Monterey 15.1 ObjectCaptureとは? MacOS Montereyで追加されたRealityKit2の新機能です。 連続して撮影された写真の画像情報及び深度情報などを用いて、写真から3Dオブジェクト(.usdzファイル)を作成できるという画期的な機能です。 WWDC2021の時に発表された機能で、 ベータの時に悪戦苦闘しながらも当時試したことを思い出します。 手順 ObjectCapture用の連続写真をiPhoneで撮影する。 撮影した連続写真を用いてMacのPhotogrammetryプログラムを実行し、3Dオブジェクトを作成する どちらもAppleからサンプルプログラムが提供されているので、今回はそちらを使って3Dオブジェクトの作成を行います。 必要条件 特にMac側で必要なスペックが高いです。 iPhone 深度情報を用いるのですが、LiDARスキャナを積んでいないiPhoneでも可能です。 ですが、LiDARスキャナを搭載したモデルの方が正確な深度情報の取得が可能なため、結果が異なります。 ※iPadでもOKです。 Mac Macに関してはグラフィック側の要件が厳しく、 ・M1 Mac(もちろんM1Pro/MaxでもOKです) ・Intel Mac の場合は Intel CPU with AMD 4GB以上 が必要です。 AMD GPUを積んでいないIntel Mac(Intel Graphicsのみ)の場合は実行出来ません。 私もWWDC2021の時点ではAMDを積んでいないIntel Macしか持っていなかったので、知人のM1Macを借りて試してました。 ObjectCapture用iPhoneアプリで写真を撮影する 以下のリンクからObjectCaptureで使用するための写真を撮るサンプルアプリがAppleDeveloperサイトからダウンロード出来ます。 https://developer.apple.com/documentation/realitykit/taking_pictures_for_3d_object_capture プロジェクト名は「CaptureSample」です。 実行するとこんな画面になります。 (ベータの時はこんな白枠なんてなかったような、、、改善されていると思います) 右下のボタンで「マニュアルモード」と「自動撮影モード」を切り替えることが出来ます。 ・マニュアルモード:自分でボタンを押して写真を撮っていきます。 ・自動撮影モード:一定間隔でシャッターが切られ、自動で撮影が進んでいきます。 自動撮影モードが個人的には便利で使いやすいと感じました。 撮影する時にはいくつかのコツがあります。 ・オブジェクトが70%以上のオーバーラップを持つように撮影し全アングルから撮影する。(これは必須) ・形状が固形で撮影中に変形しないものが適している。 ・オブジェクトの向きを変える際に、形が変わらないように注意する. ・必要な枚数はオブジェクトの複雑さにより変わるが、多い方が良い。 詳細なコツはApple公式の説明を読むのが一番です。 https://developer.apple.com/documentation/realitykit/capturing_photographs_for_realitykit_object_capture/ 以下は「CaptureSample」のヘルプ画面ですが、そこにも記載されています。 いざ撮影してみます!!が、ここが一番大変かもしれません。 ・反射して影が出来ないように照明のセッティングが必要 ・背景は一貫した背景が望ましい。 などなど、推奨した条件を満たすのはきちんとした環境を整えないと難しいです。 ということで一旦、上記を無視して、対象を以下の水筒にして床に置いて撮影してみます。 撮影すると以下のようにフォルダ分けされて保存されます。 以降はMacでの作業になるのでファイルアプリなどからAirDropなどを使ってMacに送ります。 ※それぞれのフォルダが一つのプロジェクトで使用する画像群になっています。 連続写真を用いてMacのPhotogrammetryを実行し3Dオブジェクトを作成する 写真から3Dオブジェクトを作成するのをPhotogrammetryと呼ぶのですが、Photogrammetryのコマンドラインサンプルアプリを以下のAppleDeveloperサイトからダウンロードします。 https://developer.apple.com/documentation/realitykit/creating_a_photogrammetry_command-line_app しかしながら、macのコマンドラインプロジェクトを作ったこと・使ったことが無いiOSデベロッパーの当方は実行方法がわからないので、以下の方法でやりました。 それは、プロジェクト実行時のSchemeで必要なパラメータを渡してやる方法です。 コマンドラインサンプルアプリに必要なパラメータは以下です。 ・入力ファイル(連続写真)のフォルダのパス ・出力ファイルのパス 以下のような形で設定し、実行すればプログラムは走ります。 追記:コマンドラインアプリの実行方法2 こちらが正規の手順になります。 コマンドラインアプリをビルドするとXcodeのプロジェクトフォルダに実行ファイルが追加されます。 ・デバッグの場合 /Users/(現在のユーザー名)/Library/Xcode/DerivedData/(プロダクト名)-(ランダムな識別子)/Build/Products/Debug ・リリースの場合 /Users/(現在のユーザー名)/Library/Xcode/DerivedData/(プロダクト名)-(ランダムな識別子)/Build/Products/Release 上記フォルダの中に実行ファイルが生成されています。 単純に実行した場合、以下のようにinputフォルダとoutputフォルダを指定しろと怒られます。 OVERVIEW: Reconstructs 3D USDZ model from a folder of images. USAGE: hello-photogrammetry <input-folder> <output-filename> [--detail <detail>] [--sample-ordering <sample-ordering>] [--feature-sensitivity <feature-sensitivity>] ARGUMENTS: <input-folder> The local input file folder of images. <output-filename> Full path to the USDZ output file. OPTIONS: -d, --detail <detail> detail {preview, reduced, medium, full, raw} Detail of output model in terms of mesh size and texture size . (default: nil) -o, --sample-ordering <sample-ordering> sampleOrdering {unordered, sequential} Setting to sequential may speed up computation if images are captured in a spatially sequential pattern. -f, --feature-sensitivity <feature-sensitivity> featureSensitivity {normal, high} Set to high if the scanned object does not contain a lot of discernible structures, edges or textures. -h, --help Show help information. Saving session... ...copying shared history... ...saving history...truncating history files... ...completed. [プロセスが完了しました] なのでターミナルから実行します。 なお実行形式は以下のようになっています。 ./HelloPhotogrammetry <input-folder> <output-filename> 今回の場合は以下で実行しました(schemeでやった時と同じフォルダ指定) nonakajun@MacBook-Pro Debug % ./HelloPhotogrammetry /Users/nonakajun/work/xcode/AR/ARCaptureImage/input/suitou2 /Users/nonakajun/work/xcode/AR/ARCaptureImage/output/suitou3.usdz 得られる結果は同じです。 以上、ここまで追記でした。 結果として出力された3Dオブジェクト(.usdzファイル)が以下です。 こちらはgifです。 推奨条件を無視して適当に撮影した写真からでも、デコボコではありますが、3Dオブジェクトの生成が出来ました!! 床ともしっかり分離されたオブジェクトが出来ます。 ちなみにAppleのDeveloperサイトでナイキの靴の連続写真とそこから作成した3Dオブジェクトを見ることが出来ます。 https://developer.apple.com/jp/augmented-reality/object-capture/ 環境を整えるとこんなにも綺麗な3Dオブジェクトを写真から作ることが可能です。 最後に ObjectCaptureはやってみて非常に面白いです。 あとはARオブジェクトを表示する簡単なアプリでも作って人に見せるなどすると、結構感動してもらえますよ! Macのコマンドラインはしっかり勉強して正攻法のやり方で出来るようになったら加筆したいと思います。 追記しました。 初Qiita投稿で至らない点、間違っている点などあるかと思いますが、是非ご指摘頂ければ幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む