- 1. Swift Concurrency に対応していくための Strict Concurrency Check と `@preconcurrency import`
- 2. 【Xcode】パーミッションリクエストが反映されない
- 3. 変数の前につける魔法の言葉
- 4. SwiftUI マルチプラットフォームでtoolbar対応
- 5. Elixir Desktop の iOS アプリ実装に苦労した話
- 6. [Swift] Actor Reentrancy のありがたみと注意点
- 7. 【Swift】WKWebViewでUser-Agentを取得する
- 8. FlutterでTextField(TextFormField)を使うと、大量に再描画される
- 9. `Task.init` に渡すクロージャが暗黙的に `self` をキャプチャすることの背景と注意点
- 10. 【SwiftUI】NavigationBarに画像を設定する
- 11. UITableViewCellの.disclosureIndicatorのアクセサリタイプの色適用
- 12. FlutterでiOS開発を久々に実機で検証する時につまづく
- 13. 【Swift5】Realmでデータを保存する
- 14. 【Flutter】iOS実機にてReleaseビルドが通らない場合の対処法
- 15. (超簡単)SwiftでAPIを叩いてサーバーから情報を取得する方法
- 16. バックグラウンド時やアプリ未起動時でもプッシュ通知をハンドリングする方法
- 17. iOSアプリのリポジトリ内の機密情報(API Key/Secrets etc.)のハードコーディングをなくす [Arkana]
- 18. (Swift)(PencilKit)PencilKitを使いページング機能付きお絵描きアプリの実装方法
- 19. Firebaseプロジェクトの作成(Flutter)
- 20. TestFlightで毎回表示される「輸出コンプライアンスがありません」の設定を省略する方法
Swift Concurrency に対応していくための Strict Concurrency Check と `@preconcurrency import`
## 概要
Swift Concurrency の大きな目的の1つとしてデータ競合を防ぐことがあります。 Swift 6 からはコンパイル時のデータ競合のチェックが厳しくなり、競合を起こす可能性のあるコードはコンパイルエラーになると言われています。これに備えるため、我々が日々開発しているアプリケーションのコードも Swift Concurrency に対応していく必要があるでしょう。
Swift Concurrency への移行を一気に行うのは難しいため、徐々に移行していくための仕組みが整えられています。この記事ではその中の一部として、 Xcode 14 から Build Settings の項目に追加された `Strict Concurrency Check` と、 `import` につける `@preconcurrency` アトリビュートについて紹介します。
記事中での検証は Xcode 14 Beta 4 で行っています。
## Strict Concurrency Check
Xcode 14 から、「どのくらい厳しく Concurrency Check をするか
【Xcode】パーミッションリクエストが反映されない
# 問題
`NSPhotoLibraryAddUsageDescription`を記述しているにも関わらず、記述されていない判定でクラッシュする
![スクリーンショット 2022-07-28 18.15.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/74b83dcc-8eb3-f036-3761-e44c23e97f28.png)
“`
This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.
“`
![スクリーンショット 2022-07-2
変数の前につける魔法の言葉
# はじめに
Swiftを勉強していると変数名の前にstaticやprivate、State など呪文のような言葉がついており、なんだこれ!?と思った方も多いのではないでしょうか。
ですので、それぞれどういった意味を持っているのかについてまとめました!!# static
“`swift
static var hoge
“`
そもそもこのstaticとは一体何者なのでしょうか。
それは、**値を保持し続ける変数を宣言するためのもの**である。一般的には「静的変数」と呼ばれている。staticで宣言した変数はインスタンスを生成しなくてもアクセスすることができる。
一方で、値の再度初期化ができないため、インスタンス単位でアクセスすることはできない。# アクセス修飾子
## アクセス修飾子とは
クラスや変数等がどこからアクセス可能であるかを決定するものである。## 種類
“`swift
// デフォルトの修飾子である。省略可能。
internal var hoge// クラス内でのみアクセス可能。
private var hoge// 同じファイル内でのみアクセス
SwiftUI マルチプラットフォームでtoolbar対応
# 環境
Xcode Version 13.4.1
での動作環境になります。# 概要
SwiftUIにはtoolbarというmodifierがあります。https://developer.apple.com/documentation/swiftui/view/toolbar(content:)-5w0tj
このtoolBarにはToolbarItemをはじめとしたContentが設定でき、これを設定することにより、画面にボタンなどを配置することができます。
ToolbarItemの特徴はToolbarItemPlacementが指定できる点です。https://developer.apple.com/documentation/swiftui/toolbaritemplacement
toolbarには直接ボタンの位置を指定することもできますが、キャンセルボタンとして配置(.cancellationAction)、重要なアクションとして配置(.primaryAction)、など 役割に基づいた配置指定ができます。
これを使いこなせば、SwiftUIでプラットフォームご
Elixir Desktop の iOS アプリ実装に苦労した話
## はじめに
Elixir Desktop は Phoenix LiveView を使って、 macOS でも Windows でも iOS でも Android でもネイティブアプリっぽいものが実装できるパッケージです
https://github.com/elixir-desktop/desktop
今回は iOS 版のサンプル実装を私のローカルマシン(macOS)上でビルドしようとして、
色々なエラーに引っ掛かった話を書いていきますhttps://github.com/elixir-desktop/ios-example-app
## ビルド環境
– macOS Monterey 12.4
– XCode 13.4.1
– asdf 0.10.0私は色々な案件で色々な言語、ツールをワサワサ使う関係上、
開発言語やツールの実行バージョン管理に asdf を使っていますhttps://github.com/asdf-vm/asdf
例えば Elixir なら `asdf install elixir 1.13.4-otp-24` というようにするだけで
El
[Swift] Actor Reentrancy のありがたみと注意点
## 概要
Swift Concurrency の Actor は可変な状態をデータ競合から守るためのコンポーネントです。Swift の Actor の特徴として Reentrant (再入可能)であることが挙げられます。これがなんのことで、どういうありがたみがあって、アプリ開発者として気をつけるべき注意点にどういうものがあるのかを、主に [Swift Evolution の Actor のプロポーザル](https://github.com/apple/swift-evolution/blob/main/proposals/0306-actors.md) をもとにまとめます。
前提として、自分は Swift Concurrency 以外の文脈における Actor のことはわかっていません。また、 WWDC / プロポーザルでは Reentrant / Reentrancy という言葉が使われていますが、記事中ではそれぞれ日本語で再入可能 / 再入と言うことにします。
この記事中での動作検証は Xcode 14 Beta 3 で行っています。
## Actor Reentran
【Swift】WKWebViewでUser-Agentを取得する
# 実装
“`swift
// UserAgentの取得
func getUserAgent() -> String {
webView.evaluateJavaScript(“navigator.userAgent;”) { (result, error) in
guard let userAgent = result as? String else { return }
return userAgent
}
}
“`# おわり
WKWebViewを使いこなせれば実装の幅が広がる気がします。
FlutterでTextField(TextFormField)を使うと、大量に再描画される
## 概要
TextFieldもしくはTextFormFieldを設置すると、大量(数十回)に再描写(build)される
※厳密には、MaterialPageRouteでpush(遷移)した先に、TextFieldを設置すると、同現象が発生するこの現象により、FutureBuilderやStreamBuilderと組み合わせると
「TextFieldが更新(focusやchange)される→再描画が走る→Future/StreamBuilderが走る」というループで、永遠にTextFieldへの入力が出来なかったりする。## サンプル
“`dart
// 遷移元
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Page())
);// 遷移先
class Page extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child
`Task.init` に渡すクロージャが暗黙的に `self` をキャプチャすることの背景と注意点
## 概要
`@escaping` なクロージャでは、クロージャの中で参照型の `self` のプロパティにアクセスするときなど明示的に `self` を書かなければいけません。これに対して、Swift Concurrency で使われる `Task.init` に渡すクロージャでは `@escaping` であるにも関わらず暗黙的に `self` をキャプチャするので `self` を書かなくてもいいという例外的な振る舞いをします。その背景と注意点についてまとめます。
この記事中での動作検証は Xcode 14 Beta 3 で行っています。
## `@escaping` なクロージャと `self`
本題に入る前に、まずは `@escaping` と `self` の関係について確認していきます。ある関数がクロージャを引数で受け取るとき、そのクロージャをその場ではなくあとで実行する可能性がある場合は引数に `@escaping` 属性をつける必要があります。具体的にあとで実行する可能性があるというのはどういうときかというと、
– 受け取ったクロージャをプロパティに保存する
【SwiftUI】NavigationBarに画像を設定する
# 方法1
“`diff_swift
import SwiftUIstruct ContentView: View {
var body: some View {
NavigationView {
List {
ForEach(0..<100) { index in Text("テキスト: \(index)") } } .listStyle(.grouped) + .toolbar { + ToolbarItem(placement: .navigation) { + Image("instagram") + .resizable() + .aspectRatio(contentMode: .fit) +
UITableViewCellの.disclosureIndicatorのアクセサリタイプの色適用
### 概要
– UITableViewCellで.disclosureIndicatorのアクセサリタイプを表示する際に色適用をする
– 通常のcell.tintColor設定では色適用されない※iOS13以前はできたかも### .disclosureIndicatorの色適用
このやり方がiOS標準で表示されるものと一番近い
“` swift
let chevronColor = UIColor.red
// システムイメージの表示設定を行う,iOS13以後サポート
let chevronConfig = UIImage.SymbolConfiguration(pointSize: 14, weight: .regular)
guard let chevronImg = UIImage(systemName: “chevron.right”, withConfiguration: chevronConfig)?.withTintColor(chevronColor, renderingMode: .alwaysTemplate) else { return }
let ch
FlutterでiOS開発を久々に実機で検証する時につまづく
開発も山場を迎え実機での検証を余儀なくされた時に
“`
Error: iPhone is busy: Fetching debug symbols for iPhone.
Xcode will continue when iPhone is finished. (code -10)
“`
こんなエラーに出くわす。。。– `Mac`上の`iTunes`を閉じる。
– 端末(`iphone`)の再起動。
– `Xcode`の再起動。
– `Mac`・エディタ(`VSCode`)の再起動。で上手くいかない場合は、
![スクリーンショット 2022-07-26 17.32.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/aae7078c-1523-50a0-9071-16f8add19ef1.png)
`Xcode`で端末を接続し直して、
![スクリーンショット 2022-07-26 17.33.18.png](https://qiita-image-store.s3.ap-n
【Swift5】Realmでデータを保存する
# Realmとは
– モバイル版のデータベース管理システム
– 公式ドキュメントは[こちら](https://www.mongodb.com/docs/realm-legacy/docs/swift/latest/)
# メリット
– ライブラリRealmSwiftを使用すると、アプリのモデルレイヤーで高速かつ効率的に記述できる。
– Realm Stadioアプリでデータベース管理ができる。
– データの保存、削除、検索などデータを操作しやすい
– アプリ内にデータを保存しているので、オフラインでも動くし、サーバーの負荷軽減にもつながる。# デメリット
– Structやenumが使えない。書き方に工夫が必要。
– Realm特有の仕様があるから思わぬとこでハマる。List型とか# Realmの導入
– pod installする
“`
pod ‘RealmSwift’
“`# 実装
– 今回は、PersonモデルとPokemonモデルを用意し、Personモデルに入っているPokemonモデルの配列にHitokageとZenigameとFusigidaneのデ
【Flutter】iOS実機にてReleaseビルドが通らない場合の対処法
# 開発環境
OS: MacOS
Flutter: 3.0.4
Flutter Channel: Stable
Dart: 2.17.5
Android Studio: Artic Fox | 2020.3.1 Patch4# エラーメッセージ
~~~
Automatically signing iOS for device deployment using specified development team in Xcode project: XXXXXXX
Running pod install…
Running Xcode build…
Xcode build done. 8.3s
Failed to build iOS app
Error output from Xcode build:
↳
** BUILD FAILED **Xcode’s output:
↳
Writing result bundle at path:
/var/folders
(超簡単)SwiftでAPIを叩いてサーバーから情報を取得する方法
# はじめに
SwiftでAPIを叩いてサーバーから情報を取得する方法を解説していきます。
後半にはサンプルコードを記載しています。
# この記事の対象者
・iOSアプリからAPIを叩いてサーバーから情報を取得する方法を知りたい方
・APIを叩いて情報を取得するサンプルコードが欲しい方
・汎用性の高く使いやすいAPI通信の実装方法の
# 開発環境
・Swift5
・Xcode 13.4.1
・iOS 15
#解説手順
1、今回取得する施設データ(JSON形式)
2、サーバーから取得した情報を格納するクラスを作成
3、サーバーにリクエストを送信しレスポンスを受信
4、サンプルコード
## 1、今回取得する施設データ(JSON形式)
こちらが今回APIから取得するJSON形式のデータです。
“`swift
//サーバーにある施設情報(仮)
let homeData_json = {“status”:true,”homes”:[{“homeId”:”4”,”homeName”:”A施設_1ち”,”homeType”:”2″,”homeImage”:”/img/s-study.png”},
バックグラウンド時やアプリ未起動時でもプッシュ通知をハンドリングする方法
プッシュ通知の受信イベントをバックグラウンド時にハンドリングする方法を調べても、サイレントプッシュ通知の記事ばかりが上がってきて、やり方を見つけるのに苦労したので記事にしました。
# 結論
Notification Service Extension を使う!
UNNotificationServiceExtensionのdidReceiveにOSLogを仕込んで確認したら、アプリ未起動時など状態に関わらずプッシュ通知をハンドリングできていました。(ここに通知を受信したときにやりたいことを書けばOK)### 補足
Notification Service Extension は、通知をAPNsから受信してからユーザーに見せる前にペイロードを編集したりできるapp extensionです。実装方法については[こちら](https://dev.classmethod.jp/articles/user-notifications-framework-13/)を参考にさせていただきました?
iOSアプリのリポジトリ内の機密情報(API Key/Secrets etc.)のハードコーディングをなくす [Arkana]
# はじめに
iOSアプリにおいて、サードパーティSDKなどから提供されるAPI KeyやSecretsなど、機密情報をどのようにセキュアに管理するといいでしょうか。
単純に実装するとハードコーディングや、設定ファイルなどに記述し、リポジトリにpushするようになってしまうと思いますが、セキュリティの観点からはアプリと同じリポジトリにpushするのはよろしくありません。例えばリポジトリに閲覧権限を持っている場合、API Keyを使ってAPIサービスの実行ができてしまったり、[CIツールなどでソースコードを外部からアクセスさせている場合、CIツールへ不正アクセスされ漏洩する可能性](https://about.mercari.com/press/news/articles/20210521_incident_report/)や、[ipaファイルからリバースエンジニアリングツールを使って文字列を抽出される可能性](https://nshipster.com/secrets/)もあります。
そのため、例えプライベートリポジトリだったとしても、機密情報の扱い方を考える必要性があります。
(Swift)(PencilKit)PencilKitを使いページング機能付きお絵描きアプリの実装方法
# はじめに
PencilKitを使ったお絵描きアプリの実装方法の記事はよく見かけるがページング付きのお絵描きアプリの記事は見かけません。あと実際に実務で開発した時に苦労したので、忘備録として投稿してます。
# この記事の対象者
・PencilKitを使ったお絵描きアプリを実装したい方
# このアプリでできること
・一つの画面で描画しながらページングできる
・次へボタンで新しいページを作成
・キャンバスに背景色/背景画像を指定
・キャンバスの描画情報と背景色/背景画像を合成して、1枚の画像に変換
・ToolPickerの出し入れ
またのちほど書いていきます
Firebaseプロジェクトの作成(Flutter)
## 概要
FlutterアプリとFirebaseを接続するための準備をします。
Firebaseの設定~Flutterプロジェクトのビルドが通るようになるまで### 前提
デフォルトのカウントアプリを改変して作っているので、
諸々名前が違かったらごめんなさい!
メモ程度でしかないので、ご参考までに〜## Android
![スクリーンショット 2022-06-30 18.13.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462497/ea1c6e5c-6ae0-13ae-c8a5-e70778cf7166.png)/{PROJECT_NAME}/android/app/src/main/AndroidManifest.xml
にある
“`
“`PACKAGE_NAMEをコピーし、
TestFlightで毎回表示される「輸出コンプライアンスがありません」の設定を省略する方法
# 目次
[1.やりたいこと](#1-やりたいこと)
[2.解決策](#2-解決策)
[3.まとめ](#3-まとめ)# 1. やりたいこと
AppStoreでTestFlightをアップロード後、毎回「輸出コンプライアンスがありません」が表示され、
下記のような質問事項に毎回答える必要があるため、これを省略したい。