Personal Factory

Personal Factory

iOSエンジニアの技術ブログ

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からの非同期処理をうまく書きたい方には必見の本となっています。 さて、せっかくリリースしたばかりなのですが、一部のサンプルコードがあまり良いコードではありませんでした。 すでにサンプルコードのリポジトリは修正済みですが、どのような修正があったのかをこの記事で説明したいと思います。
7 min read
技術同人誌「Swift Concurrency入門」を刊行しました
iOS

技術同人誌「Swift Concurrency入門」を刊行しました

2022年5月26日からBOOTHより、「Swift Concurrency入門」発売開始しました。 Swift Concurrencyを網羅的に学べ、さらに既存アプリへの適応方法も解説している技術同人誌です。 [https://personal-factory.booth.pm/items/3888109] https://personal-factory.booth.pm/items/3888109今回の記事では技術同人誌「Swift Concurrency入門」についてご紹介します。 Swift Concurrencyとは? Swift ConcurrencyはSwift 5.5から登場した並行処理を言語機能レベルでサポートするSwiftの新しい機能です。 今までクロージャーで実装していた非同期処理をasyncやawaitを使うことで処理の流れが格段にわかりやすくなります。 またactorを使うことで並行処理で起きがちな厄介な不具合、データ競合を簡単に防ぐこともできます。 以前集まれSwift好き!Swift愛好会 vol.65 @ オンライン [https://love
4 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
[iOS]枠線の上にViewを乗せようとしたらviewとlayerの重なり順に苦しんだ話

[iOS]枠線の上にViewを乗せようとしたらviewとlayerの重なり順に苦しんだ話

Viewに枠線をつけて、その上にViewを乗せるコードを書いていたらUIViewとCALayerの重なり順に手間取ったのでメモ的に記事にします。 souce code https://gist.github.com/SatoTakeshiX/1b9050a7ea517785e3b45ace0a38a5ac 実行環境 * Xcode 13 * iOS 15.0 * Swift 5.5 (とはいえ、内容はiOS 15でなくても動きます) 枠線の上にViewを表示したい UIViewに枠線をつけて、その上にバッチのようにUIImageViewを乗せようとしました。 ちょうど次の図のようなレイアウトです。 最初の方針として「UIViewのlayerプロパティで枠線をつけて、その上にUIImageViewを表示するAuto Layoutを設定すればよいだろう」と思っていました。 そこでこんなコードを実装しました。 SignboardというViewに緑の枠線を表示するboardViewとその上に王冠のImage ViewであるcrownImageViewを乗せるコードです。
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

[SwiftUI] PreviewProviderで実行されているかを確認

確認環境 * Xcode 12.5 * iOS 14.5 SwiftUIでPreviewされているかをプログラムで確認する方法 PreviewでViewを表示している場合、環境変数のXCODE_RUNNING_FOR_PREVIEWSの値が"1"になっています。 なので、次のように場合分けをするとプログラム上Previewで表示されているかを判別できます。 var body: some View { if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" { Text("running on preview") } else { Text("running on not preview") } } 実行するとキャンバス上でこのようなViewが表示されます。 シミュレーターではこうです。 うまく切り分けられましたね。 参考 ios - How do you check
1 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 -> 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のデータ管理 Property Wrapper編

SwiftUIのデータ管理 Property Wrapper編

SwiftUIでアプリを開発していると@Stateや@Bindingの使い分けについて迷ったりしていませんか? SwiftUIではデータを管理するProperty Wrapperがたくさんあります。 @State、@Binding、@StateObject、@ObservedObjectなどなどです。 Property Wrapperそれぞれの特徴を理解できれば、SwiftUIのアプリ開発がはかどるでしょう。 今回はSwiftUIのデータ管理を行うProperty Wrapperの使い分けについて解説します。 > この記事は私が12月9日に発表した資料、 「SwiftUIのデータ管理 [https://speakerdeck.com/satotakeshi/swiftuifalsetetaguan-li] 」を記事化したものです。 SwiftUIのデータ管理記事一覧 * SwiftUIのデータ管理 Single Source of Truth編 [https://blog.personal-factory.com/2021/01/20/whats-the-single
7 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
[SwiftUI]選択可能なUIコンポーネントの作り方【複数選択偏】
iOS

[SwiftUI]選択可能なUIコンポーネントの作り方【複数選択偏】

人はときにタップをしたらそのビューを選択状態にするコンポーネントが必要になることがあります。 ちょっと手こずったのでブログに作り方を残します。 今回は複数選択する場合を解説したいと思います。 実行環境 * Xcode 11.5 * iOS 13.5 複数選択可能なUIコンポーネント HTMLだとチェックボックスがいい例ですが、複数選択できるコンポーネントがあると素敵ですよね。 作ってみましょう。 赤、緑、青のViewがあって、タップするとViewに黒枠が追加されて選択状態がわかるようになります。 またコンソールにもタップされたら「red is selected」 。もう一度タップすると「red is not selected」というようなメッセージができるようにしています。 ViewModelの定義 まずはデータまわりを定義していきましょう。 MultipleSelectableViewModelというクラスを定義します。 final class MultipleSelectableViewModel: ObservableObject { @Publish
4 min read