SwiftUI ビュー内に直接配置するビューが多くてビルドエラーになる場合

現象

Xcode 10.15.1 / Swift 5.1.2

ドキュメントのどこに記載があるかは不明だが SwiftUI でビュー内に配置できるサブビューは 10 個までのようだ。

たとえば

struct ContentView: View {
    var body: some View {
        VStack {
            Text("1")
            Text("2")
            Text("3")
            Text("4")
            Text("5")
            Text("6")
            Text("7")
            Text("8")
            Text("9")
            Text("10")
            // Text("11")
        }
    }
}

上記のコードでは Text ビューを 10 個配置していてビルドができる状態である。

しかし、コメントアウトされている Text("11") を有効にして 11 個ビューを配置しようとすると、ビルドエラーになる。

厄介なのが、この時に出力されるビルドエラーは、直接的にビューの限度数について示したものではないから、この制約に気付きにくい。

例えば以下のエラーが出ることを確認した。ここからビュー数の制限に気付くのは不自然である。

'Int' is not convertible to 'CGFloat?'
Argument passed to call that takes no arguments

回避方法

1. ビューごとにまとめる

ビューをグルーピングして、ひとつのビューに直接配置するビューを減らす。

struct ContentView: View {
    var body: some View {
        VStack {
            Group {
                Text("1")
                Text("2")
                Text("3")
                Text("4")
                Text("5")
            }
            
            VStack {
                Text("6")
                Text("7")
                Text("8")
                Text("9")
                Text("10")
            }
            Text("11")
        }
    }
}

2. ForEach を使用する

ForEach を使った記述で、直接配置する方法を避ける。

struct ContentView: View {
    var body: some View {
        VStack {
            ForEach(1..<12) { i in
                Text("\(i)")
            }
        }
    }
}

SwiftUI @State/@ObservableObject/@EnvironmentObject のメモ

それぞれの違いなどをメモする。
間違いあるかもしれない。

@State

State - SwiftUI | Apple Developer Documentation

SwiftUI Framework に含まれる。

概要

@State の値が変更されると、ビューの表示は再計算される。
State からバインディングを取得するには binding プロパティか $ プレイフィックス演算子を使用する。($ を使用するパターンが多く見受けられる)

アクセス範囲

@State プロパティにアクセスするには、そのプロパティを持つビューのみ。(原理的にはそのビューの func を外部のビューが呼び出して、プロパティを変更する、はできる)

まとめ

有効範囲は小さく、ローカル。
@State は特定のビューに属する形のデータに使用する。
例えば、ビュー内のボタンを押して、表示を変更する、など。

@ObservableObject

ObservableObject - Combine | Apple Developer Documentation

Combine Framework に含まれる。

概要

複数のビューでデータを共有する場合は @State の代わりに @ObservableObject を使用する。

@State と似ているが、クラスのインスタンスを作成し、独自のプロパティを作成する必要がある。

監視対象オブジェクトがデータが変更されたことをビューに通知する方法はいくつかあるが、最も簡単なのは @Published プロパティラッパーを使用すること。@ObservableObject の変更はすベて自動で通知される。

アクセス範囲

複数ビューからアクセス可能。

まとめ

@State より有効範囲が広い。

例えば施設データがあり、それを List 表示する View とその先の詳細を表示する View がある場合などは施設データは @ObservableObject を使用すると良い。

@EnvironmentObject

https://developer.apple.com/documentation/swiftui/environmentobject

SwiftUI Framework に含まれる。

概要

@State が変更時にビュー更新を自動的に発生させる。
@ObservableObject が変更時にビューの更新を発生させる可能性がある。

@EnvironmentObject はすべてのビューが読み取り可能な、アプリ全体で使用できる共有データ。

まとめ

@State, @ObservableObject よりも有効範囲が広い。
アプリ全体で使用するデータに使用すると良い。

全体まとめ

有効範囲の広さ

@EnvironmentObject > @ObservableObject > @State

適切な使い道

  • @State
    • ひとつのビュー内の値変更と表示の変更
  • @ObservableObject
    • 複数のビュー内での共有するデータ(変更通知も可能)
  • @EnvironmentObject
    • アプリ全体で共有する値

参考

映画『ショーシャンクの空に』の感想

1994年 アメリ

原作 スティーヴン・キング
出演 ティム・ロビンズ、モーガン・フリーマン




スティーヴン・キング原作の映画は面白いものが多い。
たとえば以下。

スタンド・バイ・ミー

グリーンマイル

ミスト

ミスト (字幕版)

ミスト (字幕版)

ドリームキャッチャー

痩せゆく男

そして、この「ショーシャンクの空に」はキング原作の映画の中でも特に印象に残る。




この映画に描かれている人間と、アメリカの風景が好きだ。

映画のテーマは、おおざっぱに言うと、「人間の生き方」だと思う。

刑務所という粗暴で汚れた場所で、どう生きるか?

ティム・ロビンスが演じるアンディは、いままでは学歴があり知性ある人々のなかで落ち着いた生活をしていたが、冤罪で投獄され、荒い犯罪者とともに収監生活を送ることを余儀なくされた。

しかし、刑務所のなかでもアンディは「知性」や「文化」など人間的な暮らしを志向するため、高校を出ていない若い囚人に勉強を教えて高卒資格を取らせたり、ミニ図書館を作ったりする。

それにより、今まで粗暴だった刑務所内の空間が徐々に「人間らしい暮らし」ができる空間に変わっていく。

だが、品がよく学歴があり、周囲とちがうアンディは刑務所内で目立ち、騒動にもまきこまれる。悪い囚人たちに暴行、性的レイプされる日々。

また、銀行員の経歴から、刑務所の所長に強要されて、刑務所ぐるみの囚人の労働対価搾取ビジネスを手伝い、所長の隠し財産づくりに任される。

とことん、人間としての尊厳をアンディは奪われる。しかし、彼は静かに諦めずに脱獄作戦を継続し、ついに自由な世界へもどる。

ひどい環境でも人間のプライドを捨てずに、目標を成し遂げるアンディに共感し、感動する映画だ。




もうひとりの囚人の話もしよう。モーガン・フリーマン演じるレッドという囚人がいて、この映画の準主役だ。

三十代程度の若いアンディに対して、レッドは六十代程度を思わせる中年の囚人だ。

アンディが刑務所のなかで、ほかの囚人や看守と衝突するのと対照に、レッドは長いこと刑務所にいて「慣れて」おり、環境に適応し居場所をつくっていた。

実際、レッドが仮出所を望んでいない描写があることから、いわば刑務所の外の人生を「諦めた」人物として描かれている。

しかし、刑務所でアンディを助けたりと、悪意ある人間ではなく、心のどこかで、ひっそりと自由を求めいている。

だから、この映画を観た我々はまず素直に、人間の尊厳と自由を求めてもがくアンディに感情移入するが、現実に屈しいろいろと諦めて、現状を快適にしながらも良心を捨てずに生きるレッドにも感情移入する。

人間としての根底にある自由に対する生き方が、ふたつあり、どちらも理解でき感情移入できる。

だから、この映画は見終わったあと、極端な立場に立つことなく、バランスのよいさわやかな感想をもてるのだろう。

【SwiftUI】TextField で金額を入力する

NumberFomatter を TextField に設定して、以下の動作を確認

  • 米ドル、ユーロ、日本円入力のテスト
  • アルファベットなどの金額ではない入力は、キーボードを閉じたタイミングで消され、訂正される
  • 入力可能な金額の最高値
  • 入力可能な小数点以下の桁数


サンプルコードは以下。

Xcode で "Unable to boot the Simulator" が発生してシミュレータが起動しない

以下の Xcode が入っている環境(プロジェクトにより使用する Xcode のバージョンを切り替えしている)で

Xcode 11.2.1 のアップデートがあったのでこれを取り込んだ。

(これが原因かどうか分からないが)

その後 Xcode 10.1 の方のシミュレータが起動できなくなり、困った。
Xcode でアプリをシミュレータ実行しようとすると以下のエラーダイアログが表示される。

Unable to boot the Simulator.

この現象の解決に至った手順をメモする。

シミュレータのリセット

現在使用しているシミュレータをキレイにリセットしてみる。(シミュレータに保存されているデータも含め、シミュレータが全て削除されることに注意)

まずは xcode-select --print-pathXcode 10.1 の方が選択されているか、改めて確認。

次に、現在起動しているシミュレータをシャットダウンする。

$ xcrun simctl shutdown all

最後に、すべてのシミュレータを削除する。

$ xcrun simctl delete $(xcrun simctl list | grep -o '[0-9A-F]\{8\}-[0-9A-F]\{4\}-[0-9A-F]\{4\}-[0-9A-F]\{4\}-[0-9A-F]\{12\}' | xargs)
$ xcrun simctl delete unavailable

Xcode から選択できるシミュレータが一つもなくなったので、手動でシミュレータを追加して、アプリ実行を試してみる。
・・・しかし結果は変わらず、起動しなかった。

tmp フォルダの作りなおし

私の環境はこの対応をしたことでシミュレータが起動するようになった。
以下のコマンドで private/tmp を作りなおし。

$ sudo mkdir /private/tmp
$ sudo chmod 1777 /private/tmp

このあと、シミュレータ実行は無事成功した。

参考

所得税と復興特別所得税の計算

参考

所得税

所得税の税率は、分離課税に対するものなどを除くと、5%から45%の7段階に区分されています。 課税される所得金額(千円未満の端数金額を切り捨てた後の金額です。)に対する所得税の金額は、次の速算表を使用すると簡単に求められます。

課税される所得金額 税率 控除額
195万円以下 5% 0円
195万円を超え 330万円以下 10% 97,500円
330万円を超え 695万円以下 20% 427,500円
695万円を超え 900万円以下 23% 636,000円
900万円を超え 1,800万円以下 33% 1,536,000円
1,800万円を超え4,000万円以下 40% 2,796,000円
4,000万円超 45% 4,796,000円

所得税 = ( 課税所得 * 所得税の税率 ) - 所得税の控除額

復興特別所得税

平成25年から令和19年までの各年分の確定申告においては、所得税と復興特別所得税(原則としてその年分の基準所得税額の2.1%)を併せて申告・納付することとなります。

復興特別所得税 = 所得税 * 2.1%

計算例

課税所得が500万円の場合

572,500 = (5,000,000 * 0.2) - 427,500

復興特別所得税は 12,022円になる

12,022 = (572,500 * 0.021)