iOS

A collection of 96 posts
NavigationSplitViewの"Simultaneous accesses to..."クラッシュの回避方法
iOS

NavigationSplitViewの"Simultaneous accesses to..."クラッシュの回避方法

iOS 16から登場したNavigationSplitViewとSwift 5.9から登場したmacroの@Observableの組み合わせでクラッシュが発生することがあります。 この記事ではその回避方法を説明します。 動作環境 * Xcode 15 * iOS 17 クラッシュが起こる原因 ListにはSelectionValueと呼ばれる選択された保持するパラメーターが定義されています。 このSelectionValueはHashableを準拠したインスタンスを指定します。 @MainActor struct List<SelectionValue, Content> where SelectionValue : Hashable, Content : View * https://developer.apple.com/documentation/swiftui/list/#Supporting-selection-in-lists そして、NavigationSplitViewとListのSelectionValue、そしてNavigat
4 min read
UITextViewで独自のEdit Menuを表示する
iOS

UITextViewで独自のEdit Menuを表示する

実行環境 * Xcode 14.2 * iOS 16 iPhoneのメモアプリで、テキストを長押しすると出てくるメニュー。 あれを自分で作るにはどうすればいいのかを調べてみました。 そもそもあのメニューの名前はなんだろうと調べたところ、Human Interface GuidelinesにはEdit Menuという名前で紹介されていました。 Edit menus | Apple Developer DocumentationAn edit menu lets people make changes to selected content in the current view, in addition to offering related commands like Copy, Select, Translate, and Look Up.Apple Developer Documentation Edit Menuの表示
3 min read
NumberFormatterで数値を国際化
iOS

NumberFormatterで数値を国際化

個人アプリで風水アプリを作っています。佐藤タケシです。 * 玄空飛星風水 今このアプリの国際化対応をしている最中です。 玄空飛星風水は端末の方位磁石の値を読み取り、風水を判定してくれるアプリです。 こちらのキャプチャのように画面に方位磁石の値を表示しています。 値は小数点第一位まで表示しています。 この値も国際化が必要と気づいたので、そのやり方をご紹介します。 検証環境 * Xcode 14.1 * Swift 5.7.1 * iOS 16.0 * ただし、この記事で紹介するNumberFormatterはiOS 2から利用できるものです。 小数点の国際化 数値に国際化なんて必要なの?と疑問に思った方もいるかと思います。 アラビア数字を使っている限りどの国でも通用するのでは?と思う人もいるでしょう。 今回は小数点に着目しますが、実は小数点に「.(ピリオド)」を表記するのはどの国でも行われているものではありません。 世界を見渡すと、小数点の記号は主に3つの表記があります。 * イギリス式
5 min read
Xcode Cloudを個人開発で利用した感想 2022年11月版
iOS

Xcode Cloudを個人開発で利用した感想 2022年11月版

開発環境 * Xcode 14.1 * macOS Monterey 12.6 はじめに Xcode CloueはAppleが提供するAppleプラットフォームのためのCI/CDサービスです。 * https://developer.apple.com/jp/xcode-cloud/ 去年からBeta版として公開されていましたが、2022年にXcode Cloudがパブリックリリースされました。 CircleCIやBitriseなどすでにCI/CDサービスがたくさんありますが、ついにApple自身がApple開発者のためのCI/CDサービスを提供したということで、個人開発に取り入れてみました。 結果からいうと、とても良かったです。 まだまだリリースしたばかりで、機能は最低限ですが、個人開発では十分です。 逆にチーム開発としては使いづらそうな印象を受けました。 この記事では、私が個人開発で利用した内容を共有したいと思います。 皆さんのXcode Cloud利用の参考になれば幸いです。 あくまで自分の経験や感想を中心に記載するので、Xcode
4 min read
XcodeGenプロジェクトのFirebaseライブラリーをSwift Package Manager経由で追加する
iOS

XcodeGenプロジェクトのFirebaseライブラリーをSwift Package Manager経由で追加する

実行環境 * XcodeGen: 2.32.0 * Xcode 13.4.1 FirebaseをSwift Package Managerで追加したい 個人アプリで、Firebaseを利用しています。 プロジェクトの構成はXcodeGenで生成しており、FirebaseはCocoaPodsで追加させていました。 しかし、Firebase 8.0.0(2021年5月11日リリース)からSwift Package Manager(以下SPMと略します)経由で追加できるようになりました。 * Swift Package Manager for Firebase 私のプロジェクトではFirebaseのインストールがCocoaPodsの唯一の利用目的だったので、SPMに置き換えればCocoaPodsをやめれると考えました。 いろいろ調べて、XcodeGenのproject.ymlの書き方がある程度わかったのでブログに残したいと思います。 利用しているFirebaseのプロダクト 私が利用しているFirebaseのプロダクトは次の2つです。 *
3 min read
Task.initのクロージャーに[weak self]はいらない。Task.detachedとTaskGroup.addTaskも同様
iOS

Task.initのクロージャーに[weak self]はいらない。Task.detachedとTaskGroup.addTaskも同様

2022年7月29日、インプレスR&D社よりSwift Concurrencyの解説本をリリースしました。 こちらの本は一冊でSwift Concurrencyの機能をほぼ網羅したConcurrency機能の解説本です。 日本語でSwift Concurrencyを学べる解説本はまだ少ないので、Swift 5.5からの非同期処理をうまく書きたい方には必見の本となっています。 さて、せっかくリリースしたばかりなのですが、一部のサンプルコードがあまり良いコードではありませんでした。 すでにサンプルコードのリポジトリは修正済みですが、どのような修正があったのかをこの記事で説明したいと思います。
12 min read
Swift 5.5からのSwift  Concurrencyのasync/awaitの使い方
iOS

Swift 5.5からのSwift Concurrencyのasync/awaitの使い方

Swift 5.5からはSwiftの言語機能としてConcurrencyが登場しました。 これは非同期処理、並行処理のコードを簡潔かつ安全に記述できる機能です。 async/awaitを使えば、同期処理と同じような書き方で非同期処理を記述できます。 またactor型を使えばデータ競合を防ぐことができます。 この記事ではSwift 5.5からのSwift Concurrencyの機能の一つ`async/await`の使い方を解説します。
10 min read
Swift PlaygroundでConcurrencyを使う by Xcode 13.2.1
iOS

Swift PlaygroundでConcurrencyを使う by Xcode 13.2.1

Swift 5.5で登場したSwift Concurrency。 async/awaitを使うことで、並列処理を上から下に流れるように記述することができます。 どんな風に使えるかをSwift Playgroundで試そうとしたところ、Swift Playgroundではいろいろ制限があるようなのでまとめました。 検証環境 * Xcode 13.2.1 * Swift 5.5 _Concurrencyをインポートする Swift Concurrencyの機能をSwift Playgroundで使う場合、まず最初にすることは _Concurrency というフレームワークをインポートすることです。 明示的にインポートしないでConcurrencyの型を実行すると「スコープにそんな型は見つからない」とエラーになります。 手元ではコンパイルエラーにはならず、実行時にエラーが表示されました。 例えば_ConcurrencyをインポートしないでTaskを実行します。 Task.detached {} するとデバックエリアにこのようなエラーが出力されます。 error: reque
2 min read
iOS 15でNavigationBarとTabBarがデフォルトで透過される
iOS

iOS 15でNavigationBarとTabBarがデフォルトで透過される

iOS 15をXcode 13以上で開発していたところ、NavigationBarとTabBarの背景が透過されていることがわかりました。 どうやらXcode 13でビルドをした場合、iOS 15のNavigationBarとTabBarはデフォルトで背景が透過されるようです。 私のアプリでは透過ではなく、iOS 14以前と同じように背景色をつけたかったので、どう修正するのかを調べました。 開発環境 * Xcode 13.2 * iOS 15.2 NavigationBarをiOS 14以前と同じ見た目にする 背景色が透過されるようになった原因 UINavigationBarにはscrollEdgeAppearanceというプロパティがあります。 UINavigationBarAppearanceというNavigationBarの外観設定を司るクラスのインスタンスです。 Navigation ControllerがNavigation BarとScroll Viewを持っている場合で、Scroll Viewのコンテンツの端がNavigation
3 min read
VNDetectRectanglesRequestのminimumSizeについて
iOS

VNDetectRectanglesRequestのminimumSizeについて

Visionフレームワークを触っていてわからなかったことがあります。 VNDetectRectanglesRequestのminimumSizeプロパティの意味です。 minimumSizeプロパティは検出する矩形の最小サイズを指定するプロパティです。 分析する画像の矩形が指定したものよりも小さければ、分析処理をしません。 多くの矩形を分析する際は処理を軽くするために指定すると良いものです。 デフォルトが0.2になっており、0.0から1.0の値が指定できます。 let request = VNDetectRectanglesRequest() request.minimumSize = 0.2 ただこの数値の意味がわからないのです。 ドキュメント [https://developer.apple.com/documentation/vision/vndetectrectanglesrequest/2875374-minimumsize] にはこう書かれています。 > The minimum size of a rectangle to detect, as a propor
3 min read
[SwiftUI] GeometryReaderでメソッド/関数を実行したい!
iOS

[SwiftUI] GeometryReaderでメソッド/関数を実行したい!

実行環境 * Xcode 12.5 GeometryReaderでViewのサイズを取得する [SwiftUI] GeometryReaderでViewのサイズを知る [https://blog.personal-factory.com/2019/12/08/how-to-know-coorginate-space-by-geometryreader/] で解説したとおり、SwiftUIでViewのサイズを取得するにはGeometryReaderを使います。 GeometryReaderのハンドラーから渡されるGeometryProxyのインスタンスでViewのサイズがわかります。 struct LocalVariableView: View { var body: some View { GeometryReader { proxy in Text("\(proxy.frame(in: .local).debugDescription)") } } } struct LocalVariableView_
2 min read
[2021年版]XcodegenでCarthageとCocoapodsを使う最小プロジェクトを作成
iOS

[2021年版]XcodegenでCarthageとCocoapodsを使う最小プロジェクトを作成

個人アプリのプロジェクト構成をXcodegenで作り直そうかと思っています。 個人アプリはライブラリーの依存関係をCarthageとCocoapodsを使って管理していますが、Xcodegenではどういう記述でproject.ymlを書けばいいのかが検討つきませんでした。 理解を深めるために最小プロジェクトを作ることにしました。 この記事ではXcodegenでCarthageとCocoapodsを使う最小プロジェクトを解説します。 実行環境 * Xcode 12.4 * Xcodegen * Carthage: 0.37.0 * Cocoapods: ディレクトリ 今回はTryXcodegen という名前のプロジェクトを作成して、CarthageとCocoapodsでライブラリーを管理し、プロジェクト生成にXcodegenを利用します。 最終的なディレクトリ構造は次のとおりです。 主要なもののみ掲載しています。 $ tree -L 2 . ├── Cartfile ├── Cartfile.resolved ├── Carthage │ ├── Build ├
3 min read
CarthageのXcode 12エラー: This usually indicates that project itself failed to compile.を直す
iOS

CarthageのXcode 12エラー: This usually indicates that project itself failed to compile.を直す

Xcode 12でCarthageでライブラリーをビルドしようとしたら、ビルドが失敗して以下のようなエラーを出力されました。 Carthageのバージョンは0.36.0で試しています。 This usually indicates that project itself failed to compile. Please check the xcodebuild log for more details: /var/folders/jm/pyy6p95j177_btm91tj0mkdm0000gn/T/carthage-xcodebuild.WPi9jL.log > このエラーは下記issuesから引用 https://github.com/Carthage/Carthage/issues/3019 実行環境 * Xcode 12.4 * Carthage: 0.36.0 -&
2 min read
Clubhouseのスーパー楕円をSwiftUIで作る
iOS

Clubhouseのスーパー楕円をSwiftUIで作る

近年流行りだした音声SNS, Clubhouse [https://www.joinclubhouse.com/]。 デザインの特徴の1つにふわっとした丸みを帯びた楕円のアイコンがあります。 これは「スーパー楕円」と言われているそうです。 丸よりも丸みを感じる!? スーパー楕円の魅力とデザイン | Spinners Inc. [https://www.spinners.work/posts/kudakurage-superellipse-desgin/] この楕円を@tokorom [https://twitter.com/tokorom]さんがUIKitで実装してました。 スーパー楕円UIをiOS+Swiftで実装する | Spinners Inc. [https://spinners.work/posts/swift-superellipse/] この記事を読んでSwiftUIでも作りたくなったので、作ってみます。 実行環境 * Xcode 12.2 * iOS 14.2 実装方針 tokoromさんと同じようにもと記事 [https://www.spinner
4 min read
SwiftUIで開閉式メニューの作り方
iOS

SwiftUIで開閉式メニューの作り方

SwiftUIで下からニュッと表示する開閉式メニューの作り方を解説します。 > この記事は私が2020年12月22日に発表した資料、 「SwiftUIで作る開閉式メニュー [https://speakerdeck.com/satotakeshi/swiftuidezuo-rukai-bi-shi-meniyu] 」を記事化したものです。 動作環境 この記事は以下の環境で動作を確認しています。 * Xcode 12.2 * iOS 14.2 開閉式メニューを作ろう 今回作る開閉式メニューの動きをgifでみてみましょう。 親Viewを作る まずは親Viewを作りましょう。 struct ContentView: View { @State var isShowMenu = false var body: some View { ZStack { Button(action: { withAnimation { isShowMenu.toggl
4 min read
SwiftUIのデータ管理 Single Source of Truth編
iOS

SwiftUIのデータ管理 Single Source of Truth編

SwiftUIでアプリを開発していると@Stateや@Bindingの使い分けについて迷ったりしていませんか? SwiftUIではデータを管理するProperty Wrapperがたくさんあります。 @State、@Binding、@StateObject、@ObservedObjectなどなどです。 Property Wrapperそれぞれの特徴を理解できれば、SwiftUIのアプリ開発がはかどるでしょう。 今回はSwiftUIのデータ管理に欠かせないSingle Source of Truthという考え方について解説します。
3 min read
UITableViewをコードで実装する最速の方法
iOS

UITableViewをコードで実装する最速の方法

UITableViewでリスト表示を実装するさい、よくやるやり方は、StoryboardやXibファイルでCellを作って、そのidentifierをView Controllerで指定する方法です。 ですが、UITableViewCell標準の表示で十分な場合にファイルが分かれるのは面倒です。 なんとかコードで済ます方法がないかと探したらありましたのでご紹介します。
2 min read
[iOS 14]WidgetでDeep Link作成
iOS

[iOS 14]WidgetでDeep Link作成

iOS 14からWidgetという機能が登場しました。これはアプリを起動しなくてもHome画面にアプリ情報をユーザーに届けられる機能です。 今回はWidgetをタップした時に特定のアプリ画面が開けるようにする、Deep Linkの作成方法について解説します。 検証環境 * Xcode 12.2 * iOS 14.2 WidgetとDeep Link Widgetをタップすると何も実装しなければ、本体アプリが起動されます。 しかし、Widgetに表示されているコンテンツと関連した画面に遷移できればユーザー体験が向上します。 そのためにはWidgetにDeep Linkを作る必要があります。 Widgetのサイズとリンクの数について まず最初にWidgetのサイズとリンクの数についてお話します。 開発者が作れるWidgetの大きさはSmall, Medium, largeの3つです。 実はWidgetはサイズによっておけるリンクの数が決まっています。 Smallサイズはひとつだけで、MediumサイズとLargeサイズは複数置くことができます。 例えば、Appleの
3 min read
[iOS 14] Widgetでカウントダウン
iOS

[iOS 14] Widgetでカウントダウン

WidgetのViewを更新するにはTimelineProviderプロトコルのgetTimelineメソッドを実装してタイムラインという何時何分にどんなデータでViewを更新するのかをあらかじめWidgetKitに伝える必要があります。 Todoアプリなどでイベントをカウントダウン表示したい場合を想定します。 毎秒更新するようにタイムラインを作成すればうまくいくかと思いきや、各アプリによってWidgetを更新できる回数は決まっています。 TimelineProviderのドキュメントにはこう書かれています。 > Each configured widget receives a limited number of refreshes every day. Several factors affect how many refreshes a widget receives, such as whether the containing app is running in the foreground or background, how frequently the widge
2 min read
iOS

[SwiftUI]半透明の色を設定する

検証環境 * Xcode 11.6 * iOS 13.6 半透明の色を設定する Colorに.opacity修飾子メソッドを実行すると色の透明度を設定することができます。 Rectangle() .foregroundColor(Color.black.opacity(0.5)) 50%の透明度で指定しています。 キャプチャはこちら。 20%ぐらいだとこのぐらい。 .foregroundColor(Color.black.opacity(0.2)) 100%だとこのぐらいの色になります。 .foregroundColor(Color.black.opacity(1)) まとめ 背景色などを半透明にしたいなと思ったときに.opacityは使えそうです。 宣伝 インプレスR&D社より、「1人でアプリを作る人を支えるSwiftUI開発レシピ」発売中です。 「SwiftUIでアプリを作る!」をコンセプトにSwiftUI自体の解説とそれを組み合わせた豊富なサンプルアプリでどんな風にアプリ実装すればいいかが理解できる本となっています。 iOS 14対
1 min read
PMとデザイナーが知るべきiOS 14 新機能Widgetのすべて
iOS

PMとデザイナーが知るべきiOS 14 新機能Widgetのすべて

6月にWWDC20が発表され、次期iOS 14にはWidgetという新機能が登場することが判明しました。 Apple、iOS 14でiPhoneの体験を刷新 [https://www.apple.com/jp/newsroom/2020/06/apple-reimagines-the-iphone-experience-with-ios-14/] より抜粋 この記事ではWidgetのUI/UXをまとめます。 PMとデザイナーが「Widgetを自プロダクトに導入する」にあたって、「Widgetがどういうものなのか」を理解するためにこの記事が役に立つでしょう。 記事の内容はUI/UXに絞っているため技術的な観点からの言及は少ないです。 予めご了承ください。 免責 8月10日現在、WidgetについてはApple Beta Software Programにあたるため、スクリーンショットを独自でとることはNDAの観点から避けなければいけません。 この記事ではAppleの公式サイト、WWDCのVideoからキャプチャーを利用いたします。 引用と判別ができるよう、キャプチャーを取得した
9 min read
[SwiftUI]選択可能なUIコンポーネントの作り方【ラジオボタン偏】
iOS

[SwiftUI]選択可能なUIコンポーネントの作り方【ラジオボタン偏】

前回 [SwiftUI]選択可能なUIコンポーネントの作り方【複数選択偏】 [https://blog.personal-factory.com/2020/07/11/how-to-create-selectable-ui-component-by-swiftui-in-multiple/] で複数選択ができるUIコンポーネントをSwiftUIで作る方法を解説しました。 今回はHTMLのラジオボタンのように複数あるViewの内一つのみ選択するコンポーネントを作ってみます。 まずは動きをみていきましょう。 赤、緑、青のビューがあって、赤をタップすると黒枠が追加されて選択状態ということがわかります。デバックエリアにも「selected box is red」と出力されます。 他のビュー、例えば緑をタップすると、赤のビューの黒枠は消えて、緑のビューが黒枠でおおわれるようになるというしだいです。 選択するViewのタイプを定義 ユーザーが何を選択したかを判定できるようにBoxTypeというenumを定義します。 enum BoxType: String { case unkn
4 min read