見出し画像

【じっくりSw1ftUI32】実践編2〜第17章 SwiftUIモードでのXcode15の使用〜SwiftUIの開発環境(プラットフォーム)Xcodeを動かしてみよう🕺

さてと、前回

SwiftUIの概要

についてはまとめたつもりなので〜〜〜今回は、いよいよ

SwiftUIでアプリを作る開発環境(プラットフォーム)=Xcode

を動かしていく🕺

  • Canvas

  • LivePreview

  • デバッグ

などなど様々な機能があって、

知っておくと色々と便利な機能も多い

パフォーマンスが雲泥の差

になるので、ここも

💃読み飛ばさずにしっかりやってく🕺
👉こんなところは読み飛ばしても、どうせ使っていれば馴れる
みたいに思い込む人もいるけど、
案外使わずに一生知らない人も出てくるのでしっかりやる!
=そのために、オイラは学び直してるところもあるので〜〜〜

ま、今回の学び直しなんかもいらないって人は

で本文はそのまま公開されてるみたいなので、そちらでどうぞ〜〜〜
さてと、

じっくり第16章を読んでく

まずは、

SwiftUIでの環境での開発は、
UIKitでストーリーボードでやるのと大きく異なる

ってことを言ってんね👀
※UIKitでの開発を知りたい人は、【徒然iOS】マガジン

【気ままにUIKit】シリーズ

で、しっかりまとめてるつもりだから、そちらを参考にしてみてね!

なんかでも書いてるとおり、

SwiftUIを知るともはやUIKitでの開発には戻れない
👉マジで機能を改修する作業コストが面倒臭い
(コーディングベースではない全てのローコードツールでも言えることだけどね
👀💦

なので。次章以降で触れてく各モディファイアをUIKitの各パーツなんかと比較するのも面白いとは思うけど。

SwiftUIだと不要なOutletやAction接続なんかも必要になってきて面倒臭い

ってのが

肌感覚で分かる

と思う。ま、生真面目で努力と暗記バカが多い日本の自称、職人さんたちからは、

  • いや、両方使えるべき

  • 両方知っておいて当然

  • 積み上げが必要だから、UIKitを使いこなせないとSwiftUIは使いこなせない

なんて思い込みが聞こえてきそうなんだけど、
単純にSwiftUIもUIKitも、XcodeでiOSアプリを開発する際に利用するフレームワークが違うだけで、別にUIKitが使える前提でSwiftUIは開発されてるなんてこたあない

👉どのフレームワークを使うかだけの違い
=いきなりSwiftUIだけ学んでアプリ開発して全然OK
SwiftUIにない一部の機能だけUIKitで使えばいい程度

なんで、
勝手な思い込みとか使命感で、自分の学習コストを2〜3倍に跳ね上げないでね💦(勝手な職人像で余計な遠回りをしてる個人や企業が日本には本当に多い)

でも書いたとおり、

1冊にまとまったロクな技術書すら作れないくせにね、、、💦

Xcode15でSwiftUIモードを使おう

Xcode自体がまだ自分のMacに入っていないって人はいないとは思うんだけど(いたら、どうやって今までやってたシンタックス編までを動かしていたのか?🧐とは思ってしまうけど、、、💦)もし入っていないなら、

のリンク先の過去の記事なんかに、

Xcodeのインストール方法なんかはまとめてるから参考にしてみてね

インストールされたら、ドックなんかに追加したXcodeのアイコンをクリック

こいつです
Create New Project…
をクリック
そのままNextをクリック
Nameにテケトーなプロジェクト名を入力はするんだけど、
ここの2つがこれになってることを確認してNextをクリック
今回はNoneを選んで、、、
(後から組み込むのが面倒なのでいつもはNone以外をオイラは使ってるけどね💦)

てな感じで

直感的に先に進んでいく

と、いつもどおり開発するプロジェクトができる🕺

ここでポイント1:マルチプラットフォーム=複合的に対応した開発環境なので

  • iOS

  • WatchOS

  • MacOS

  • tvOS

にも対応してる。しかも、最小限のコードの変更で、

最初はiOSなんかで作ったプロジェクトを別のOSに簡単に変更できる
(@_@)知らんかった、、、

BundleするURLなんかはリバースさせたものが出てくるって

Xcodeだと今までどおりの当たり前の作法

もちゃんと書いてあんね👀

プロジェクトが完成して出てきた〜〜〜

ここでポイント2:画面の構成としては、

大きくA、B、C、D、Eって感じで分かれてんね
(冒頭のサイトのキャプチャをそのまま流用)

各エリアの名前としては、

  • A:プロジェクトナビゲーター

  • B:コードエディター

  • C:プレビューキャンパス

  • D:アトリビュートインスペクター

  • E:コンソールエリア

でさらに、そいつらの役割としては〜〜〜

  • A:プロジェクトナビゲーター = プロジェクト内のファイルを管理

  • B:コードエディター = 実際に組み込む作業をする

  • C:プレビューキャンパス = シミュレータや実機を使わずに動作検証できる

  • D:アトリビュートインスペクター = 色やサイズ各状態などをコードを打たずに編集できる

  • E:コンソールエリア = 実行時にPrintなんかで処理を見れる

てな感じだね。ちなみに、

矢印アイコンのすぐ左側のアイコンをクリック
出てくるメニューの中のMinimapをクリックすると〜〜〜
コードの全体像が見れるビューが追加される

キャンパス自体も

チェックが入ってるのをクリックしてチェックを外すと
消すことができる👀
もう一回チェックを入れ直すと元に戻せる🕺
👉プレビューとかが邪魔な時は便利

ここでポイント3:各エリアは自分で使いやすいようにカスタマイズできる

コード作業なんかに集中したい時は〜〜〜

一番左上のアイコン
一番右上のアイコン
デバッグエリアの右上のアイコン

なんかもクリックして、CanvasやMinimapのチェックも外してあげると

てな感じでコードエディターだけにすることも簡単👀

MacBook Airとか使っていて画面が小さい時にどうしてもプレビューとかが邪魔で作業が捗らない時とか、Canvasが常に動いていて、待機時間がうざいなんてときには使ってみてね〜〜〜

ここでポイント4:Canvas内の構成

次は、プレビュー画面が表示されるCanvasの中の構成に入ってく👀

コイツな!

ここも冒頭のリンクから、図を流用するけども

A~Dに分かれていて〜〜〜
  • A:キャンバスエリア

  • B:サイズボタン

  • C:ピンボタン

  • D:プレビューツールバー

って名前で、各機能としては

  • A:キャンバスエリア = 現在のビューを表示する

  • B:サイズボタン = 表示の拡大や縮小、100%なんかにする

  • C:ピンボタン = 同じファイルに複数のプレビューなんかが

  • D:プレビューツールバー = プレビューの詳細機能切り替え

って感じ。例えば、ビューを同じファイルに一個増やして、

import SwiftUI

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}
#Preview {
    ContentView()
}

struct SubView: View {
    var body: some View{
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("こんにちは、SwiftUI🥺")
        }
        .padding()
    }
}
#Preview{
    SubView()
}

てな感じで、サブビューを一個追加して

てな感じで出すことはできるんだけど、、、

コンテントビューで表示を固定したい時に〜〜〜

てな感じでピンで固定ができるみたいだね👀
(オイラはあんまりビューを多く作ることがないから、使うことは少ないけどね💦)

さてと次は、プレビューエリアの各詳細機能の切り替え

コイツら

を紹介してく🕺ここも冒頭のリンク記事の図を流用して〜〜〜

プレビューの詳細機能

A〜E

名前としては、

  • A:ライブモード

  • B:選択モード

  • C:バリアントボタン

  • D:ローテートボタン

  • E:デバイス切り替え

って感じ。そこに簡単な説明を付けると、

  • A:ライブモード = シミュレーターとか実機を使わずに実際の動きを確認

  • B:選択モード = ライブではなくあくまでもビュー単体で確認

  • C:バリアントボタン = 色合いとか文字サイズなんかを切り替え

  • D:ローテートボタン = 縦向きや横向きなどを切り替え

  • E:デバイス切り替え = iPhoneやiPadなんかの各機種を選択する

実際に動かしてく

ライブモード
選択モード
バリアントモードで、色合いをクリックすると〜〜〜
てな感じで、ライトモードとダークモードを比較してくれる
今度はオリエンテーションをクリック
縦向き、横向きでどうなるか比較してくれる
今度は、ダイナミックをクリック〜〜〜
各テキストで文字サイズを設定するとどんな表示を示してくれる
ローテートで、OrientationをONにして、LandScapeLeftをクリック
横向きにできた〜〜〜〜
コイツで機種をiPad 11-inchなんかをクリック
てな感じで機種を簡単に選択表示できる

ここでポイント5:ここはオイラの経験談だけど

⒈ふたつ前の画像と今の画像を比較してもらいたいんだけど、機種が変わった=画面サイズが違うはずなのに、どちらも文字がちゃんと中央に表示できてる👉これはVStackってモディファイアをコードで入れてるのもあるんだけど、

・Objective-CとかUIKit

(StackViewControllerを使わない限りは)
AutoLayoutって自分で各機種の画面サイズごとに位置やサイズ、アスペクト比なんかを細かく設定しないといけなかった
=結構、これが沼る作業でここでiOS開発を断念する人も多かった

・SwiftUI

AutoLayoutという概念がなくなった
👉よりシンプルでモダンにビューを簡単に作れるようになった

⒉これまでの記事で書いたコードテンプレートを自分で実際に動かした人はお気付きだと思うけど、

ライブビューでも、リストから他のビューに遷移するアプリの場合は、実機かシミュレーターで動かさないと、リストから先に遷移しない

なんてことも多いから、

ライブビューでやってるのに、想定してる動きにならない
👉自分の組み方が何かおかしいんだろうか?

って考えて、コードと睨めっこしてうんうん唸るより先に、

シミュレーターや実機で動かしてみてね。

実は、コンテントビューから行かないと次の画面が開かないってことも多い
(理由は簡単なんだけど、他の章の話をしてからの方が理解しやすいと思うのでここではまだやらない笑)

とりあえず、次に行くので

元に戻してと、、、

ここでポイント6:SwiftUIで作業するってことは

以下を含んで作業してるってことらしい

  • ビュー追加

  • モディファイアを使ったロジックを追加

  • 双方向性な宣言と他のデータインスタンスへの結びつけ

👉コードエディターの中でモディファイアと構築でやっていける

と、ここで

ここでポイント7:モディファイアって(今回から急に出てきたけど)何?

って人もいると思うので〜〜〜

って意味らしいんだけど、オイラ的には、

いい感じにする!

って感じ。それを実際に今から見ていく〜〜〜今までで作ってるサブビューだと、

てな感じで文字が小さい

これを

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}
#Preview {
    ContentView()
}

struct SubView: View {
    var body: some View{
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("こんにちは、SwiftUI🥺")
                .font(.title)//追加
        }
        .padding()
    }
}
#Preview{
    SubView()
}

すると〜〜〜

文字が大きくなった〜〜〜

これがモディファイア

👉自分のデザインしたい感じに調整する機能

ってイメージ。で、コードベースなんで、

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}
#Preview {
    ContentView()
}

struct SubView: View {
    var body: some View{
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("こんにちは、SwiftUI🥺")
                .font(.title)
            Text("こんにちは、SwiftUI🥺")
                .font(.largeTitle)
            Text("こんにちは、SwiftUI🥺")
                .font(.title2)
            Text("こんにちは、SwiftUI🥺")
                .font(.title3)
            Text("こんにちは、SwiftUI🥺")
                .font(.caption2)
        }
        .padding()
    }
}
#Preview{
    SubView()
}

てな感じで、

いとも簡単に色んなサイズを試すことも出来る🕺

と、今追加したコードは削除して

元に戻して〜〜〜

お次は、ビューの構築

例えばテキストビューをもうひとつ追加するとしたら、コードでさっきみたいにできなくはないし、馴れてくるとそっちが楽ではあるんだけど、

右上の+をクリック
ライブラリパネルの一番左のアイコンをクリック
Textを選ぶ
追加したい箇所にドラッグすると、
てな感じで簡単に追加でけた

ここで、さっき出てきた

アトリビュートインスペクター

を開いて、

右上にあったマークをクリックして
出てくる項目に〜〜〜
てな感じでテケトーに調整していくと〜〜〜
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}
#Preview {
    ContentView()
}

struct SubView: View {
    var body: some View{
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("こんにちは、SwiftUI🥺")
                .font(.title)
            Text(/*@START_MENU_TOKEN@*/"おはこんばんちは、アラレちゃん"/*@END_MENU_TOKEN@*/)
                .font(.largeTitle)
                .fontWeight(.bold)
                .foregroundColor(Color.red)
        }
        .padding()
    }
}
#Preview{
    SubView()
}

てな感じのコードを追加してくれて〜〜〜

てな感じで構築してくれる!🕺
👉馴れるまではこっちの方が早いかもね👀

ここでポイント8:Jump to Definitionを使う

ライブラリに入ってる各ビューを追加したまではいいんだけど、そのビューの詳細を確認したい時にどうする?

よくXcodeの機能自体を理解してなくて、コードを打てるからなんとなく理解しただけの人で多い回答が、

  1. WEBで調べる

  2. 本で調べる

  3. Apple公式サイトで確認する

だと思うんだけど

  1. WEBで調べる(じゃ、検索でヒットしなかったらどうする?)

  2. 本で調べる(使ってる本が古くて最新の情報がなかったらどうする?)

  3. Apple公式サイトで確認する(そこで理解できなかったらどうする?)

そこで使えるのが、

Jump to Definition

例えば、さっき追加したTextビューの詳細を知りたい時に、

Textをドラッグ
controlキーを押しながらクリック
出てくるメニューのJump to Definitionをクリック
出てくる候補のうちTextを今回は選択
てな感じで解説ページに飛ぶので〜〜〜
そこで詳細を簡単に確認できる🕺

これはUIKitでも同様に使える機能で重宝するので〜〜〜

でも、【気ままにUIKit】シリーズで具体的な組み込みをやる前に

で書いてたりする。

他にも本文では、

再利用できるサブビューなんかを構築しとくと
強力なパフォーマンスを発揮する

なんかも親切に書いてくれてるね🌱

さてと、次はみんな大好きシミュレーター

ここの部分の話🕺

Xcodeはシミュレーター機能が充実してる

ので、正直、オイラは9年くらい前に買った、すでにiOS17にアップグレードできなくなってるiPhone8Plusしか自分のスマホは持っていないんだけど、

iOSアプリ開発に困ったことがない

くらい🕺な強力な機能なのでじっくりレッツゴ!

ここも冒頭のサイトから図を流用すると、、、

てな感じで

名前としては、

  • A:停止ボタン

  • B:実行ボタン

  • C:デバイス選択メニュー

  • D:Xcodeツールバー

って感じみたいだね。それに説明を付けると

  • A:停止ボタン = 実行中のシミュレーターを停止

  • B:実行ボタン = 作ったアプリをシミュレーターで実行

  • C:デバイス選択メニュー = シミュレーターで実行したい機種なんかを選択

  • D:Xcodeツールバー = Xcodeの状態を表示

って感じかな🧐

作ったアプリで、シミュレーターにしろ実機しろ

FaceID

なんかでライブプレビューでは確認できない機能を確認するときにも使える的な感じで書いてんだけど、オイラなら、これまでの記事でゆーてるとおり、

頭の中だけでコードを書いて動かすのではなく、どんな簡単なものでもシミュレーターで作った直後に動かして、想定どおりに動いてるかを確認してるね=インクリメンタル型な構築方法
👉想定の中だけで確認して動かさないなんて、ゴミコードになっていたら、リリース前に大変😱

からね。せっかく簡単に、便利に、すぐに確認できる機能が充実してるのに、使わないなんて

愚か者としか言いようがないでしょ。
消化器置いてる家なのに、火事になった瞬間に火事になってないと言い張って、消化器を使わずに全焼させてるようなもの

「鍵を落とした場所が暗いからって
明るいところで鍵を探し続けるバカはいない」

機種はこんな感じで選択できる

そこにない機種でさらに確認が必要なら、

を参考に〜〜〜

てな感じで追加も可能だからやってみてね〜〜〜

で、実際、実行するといつも記事公開後でやってる

てな感じになるので〜〜〜

実機でやる場合

AppleIDの登録されたデバイスじゃないと実行できない的なことを書いてるので注意してね〜〜〜〜👀💦

実機とシミュレーターの設定画面

コイツで、開けるみたいだけど、
思いっきりオイラのIDなんかも載ってる画面に飛んでしまうので〜〜〜
開いた画面の左上のDeviceメニュー>右上のコイツで色々設定を切り替えたりできるみたい

ネットワークテストも有効化できたり、

  • Take Screenshotsでスクショを撮る

  • Open Recent Logsでログを確認する

  • Open Consoleでコンソールフォルダを表示

なんてことも出来るみたいね👀💦

かなり機能が充実してるし、使いこなせたらかなり便利💦

ここでポイント9:シミュレーター実行中に使える機能

エラーが起きたら、
てな感じでエラーもナビゲーションしてくれるし、
パフォーマンスも監視して表示してくれる
Memoryをクリックするとこんな感じ
Discをクリックするとこんな感じ
ネットワークをクリックするとこんな感じ

ここでポイント10:ビューの階層をチェック

さらに、実行中にビューの階層構造を確認することもできる。ここはちょっと、これまでの記事で作った、コードテンプレートで実行してみるけど〜〜〜

View UI Hierarchyをクリック
てな感じで、ビューの階層構造を確認できるのね👀
知らんかった
しかもドラッグしながら動かすと
てな感じで立体で確認できるし💦👀
凄すぎ!!!!!

ちなみに本文には載ってないけど、

View Memory Graph Hierarchyをクリックすると
各メモリー使用量も階層構造で教えてくれる優れ物みたいだね👀

以上。

まとめ

すっげ〜〜〜色んな機能が出てきたから、Xcodeが難しそうってイメージかもしれないけど、

  1. コードを書いたり後リビュートインスペクターなんかでビューを作る

  2. デバッグする

  3. シミュレーターなんかで検証する

って一連の各作業でそれぞれ使える機能をここで一気にまとめてるだけだし、できることから使っていけばオイオイ嫌でも身に付く機能。どころか使いこなせると

便利な機能ばかり

なんで、

ビビらずに色々自分の手で動かしてみてね〜〜〜

  • 知得:知る=知る

  • 習得:動かして好きになる=理解する

  • 体得:動かすのが普通になる=身につける

って感じで自分の手でコードを書いたり、書いたコードを動かしたりしていかないと最初のうちは、身についたことにならないからね〜〜〜

どんな情報も触れただけでは知っただけで、理解したことにすらならない

最終的に、

自分の作りたいアプリがゼロからひとりで作れるようになればいいだけ

だし、いくらこんな記事だけを読んだだけで、全部わかった、理解した気になって、簡単そうってイメージを勝手に抱いて、

SwiftUIなんて簡単だ!誰でも出来る

なんて周囲に豪語しておきながら、いざ自分でゼロから作ろうとしても

どうしていいかわからない、ゼロから一人で簡単そうなアプリも作れない🥺

なんて恥ずかしいだけだからね〜〜〜

COBOLとかC、Java、WEBくらいで止まってるレガシーエンジニアの巣窟みたいな会社(結構な巨大企業)なんかで、実際、

「(鼻で笑いながら)SwiftとかKotlinみたいな言語とかRPAなんか簡単でしょ。そんな言語ができるくらいでプログラマとかエンジニア名乗っちゃダメ」

とか言いながら、いざ自分たちで作ってるとか公開してるアプリが、

  • 納期を何ヶ月も遅れてリリースしたのに、潜在バグでバグりまくって誰も使わない

  • 機能どころかポータル画面のレイアウト自体がわかりにくく、使いにくすぎて炎上の嵐

なんて星の数ほどあるからね。

あれ?簡単なんじゃなかったっけ🧐

って感じでね。ま、そんな恥ずかしいことにならないように、

頭だけで理解した気にならず、どんな簡単だと頭では思えることも
最初のうちは、実際に手で動かしながら、体に馴染ませていってね〜〜〜

今回のまとめコード

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}
#Preview {
    ContentView()
}

struct SubView: View {
    var body: some View{
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("こんにちは、SwiftUI🥺")
                .font(.title)
            Text(/*@START_MENU_TOKEN@*/"おはこんばんちは、アラレちゃん"/*@END_MENU_TOKEN@*/)
                .font(.largeTitle)
                .fontWeight(.bold)
                .foregroundColor(Color.red)
        }
        .padding()
    }
}
#Preview{
    SubView()
}

Apple公式

さてと、次回は

階層構造の確認機能も今回出てきたし、SwiftUI構築の理解に必要な

第18章 SwiftUIアーキテクチャ

をやってく〜🕺

今回でついに

やってる範囲も25%を超えたね👀

これからXcodeのみの操作でよくなるから、ペースもさらに上がるはず💦

記事公開後、

でやったやり方でビューを今回も追加🕺

てな
てな
感じで
ハイ、完了🕺

今回のコード

//フレームワーク
import SwiftUI
import WebKit

//ビュー管理構造体
struct ListiOSApp17DevelopmentEssentials: Identifiable {
    var id: Int
    var title: String
    var view: ViewEnumiOSApp17DevelopmentEssentials
}
//遷移先の画面を格納する列挙型
enum ViewEnumiOSApp17DevelopmentEssentials {
    case Ch1
    //じっくり13で追加
    case Ch2
    //じっくり14で追加
    case Ch3
    //じっくり15で追加
    case Ch4
    //じっくり16で追加
    case Ch5
    //じっくり17で追加
    case Ch6
    //じっくり18で追加
    case Ch7
    //じっくり19で追加
    case Ch8
    //じっくり20、21で追加
    case Ch9
    //じっくり22、23で追加
    case Ch10
    //じっくり24で追加
    case Ch11
    //じっくり25で追加
    case Ch12
    //じっくり26で追加
    case Ch13
    //じっくり27,28で追加
    case Ch14
    //じっくり29で追加
    case Ch15
    //じっくり31で追加
    case Ch16
    //じっくり32で追加
    case Ch17
}
//各項目に表示する文字列
let dataiOSApp17DevelopmentEssentials: [ListiOSApp17DevelopmentEssentials] = [
    ListiOSApp17DevelopmentEssentials(id: 1, title: essentialsChapter1Title, view: .Ch1),
    //じっくり13で追加
    ListiOSApp17DevelopmentEssentials(id: 2, title: essentialsChapter2Title, view: .Ch2),
    //じっくり13で追加
    ListiOSApp17DevelopmentEssentials(id: 3, title: essentialsChapter3Title, view: .Ch3),
    //じっくり15で追加
    ListiOSApp17DevelopmentEssentials(id: 4, title: essentialsChapter4Title, view: .Ch4),
    //じっくり16で追加
    ListiOSApp17DevelopmentEssentials(id: 5, title: essentialsChapter5Title, view: .Ch5),
    //じっくり17で追加
    ListiOSApp17DevelopmentEssentials(id: 6, title: essentialsChapter6Title, view: .Ch6),
    //じっくり18で追加
    ListiOSApp17DevelopmentEssentials(id: 7, title: essentialsChapter7Title, view: .Ch7),
    //じっくり19で追加
    ListiOSApp17DevelopmentEssentials(id: 8, title: essentialsChapter8Title, view: .Ch8),
    //じっくり20、21で追加
    ListiOSApp17DevelopmentEssentials(id: 9, title: essentialsChapter9Title, view: .Ch9),
    //じっくり22、23で追加
    ListiOSApp17DevelopmentEssentials(id: 10, title: essentialsChapter10Title, view: .Ch10),
    //じっくり24で追加
    ListiOSApp17DevelopmentEssentials(id: 11, title: essentialsChapter11Title, view: .Ch11),
    //じっくり25で追加
    ListiOSApp17DevelopmentEssentials(id: 12, title: essentialsChapter12Title, view: .Ch12),
    //じっくり26で追加
    ListiOSApp17DevelopmentEssentials(id: 13, title: essentialsChapter13Title, view: .Ch13),
    //じっくり27,28で追加
    ListiOSApp17DevelopmentEssentials(id: 14, title: essentialsChapter14Title, view: .Ch14),
    //じっくり29で追加
    ListiOSApp17DevelopmentEssentials(id: 15, title: essentialsChapter15Title, view: .Ch15),
    //じっくり31で追加
    ListiOSApp17DevelopmentEssentials(id: 16, title: essentialsChapter16Title, view: .Ch16),
    //じっくり32で追加
    ListiOSApp17DevelopmentEssentials(id: 17, title: essentialsChapter17Title, view: .Ch17),
    
]
struct iOSApp17DevelopmentEssentials: View {
    var body: some View {
        VStack {
            Divider()
            List (dataiOSApp17DevelopmentEssentials) { data in
                self.containedViewiOSApp17DevelopmentEssentials(dataiOSApp17DevelopmentEssentials: data)
            }
            .edgesIgnoringSafeArea([.bottom])
        }
        .navigationTitle("iOS開発の章目次")
        .navigationBarTitleDisplayMode(.inline)
    }
    //タップ後に遷移先へ遷移させる関数
    func containedViewiOSApp17DevelopmentEssentials(dataiOSApp17DevelopmentEssentials: ListiOSApp17DevelopmentEssentials) -> AnyView {
        switch dataiOSApp17DevelopmentEssentials.view {
        case .Ch1:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh1()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり13で追加
        case .Ch2:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh2()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり13で追加
        case .Ch3:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh3()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり15で追加
        case .Ch4:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh4()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり16で追加
        case .Ch5:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh5()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり17で追加
        case .Ch6:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh6()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり18で追加
        case .Ch7:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh7()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり19で追加
        case .Ch8:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh8()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり20、21で追加
        case .Ch9:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh9()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり22、23で追加
        case .Ch10:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh10()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり24で追加
        case .Ch11:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh11()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり25で追加
        case .Ch12:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh12()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり26で追加
        case .Ch13:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh13()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり27,28で追加
        case .Ch14:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh14()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり29で追加
        case .Ch15:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh15()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり31で追加
        case .Ch16:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh16()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
            //じっくり32で追加
        case .Ch17:
            return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh17()) {
                Text(dataiOSApp17DevelopmentEssentials.title)
            })
        }
    }
}

#Preview {
    iOSApp17DevelopmentEssentials()
}
import SwiftUI
import WebKit

//iOSApp17DevelopmentEssentialsCh17.swift
//ビュー管理構造体
struct ListiOSApp17DevelopmentEssentialsCh17: Identifiable {
    var id: Int
    var title: String
    var view: ViewEnumiOSApp17DevelopmentEssentialsCh17
}
//遷移先の画面を格納する列挙型
enum ViewEnumiOSApp17DevelopmentEssentialsCh17 {
    case Sec1
}
//各項目に表示するリスト項目
let dataiOSApp17DevelopmentEssentialsCh17: [ListiOSApp17DevelopmentEssentialsCh17] = [
    ListiOSApp17DevelopmentEssentialsCh17(id: 1, title: essentialsChapter17SubTitle, view: .Sec1)
]
struct iOSApp17DevelopmentEssentialsCh17: View {
    var body: some View {
        VStack {
            Divider()
            List (dataiOSApp17DevelopmentEssentialsCh17) { data in
                self.containedViewiOSApp17DevelopmentEssentialsCh17(dataiOSApp17DevelopmentEssentialsCh17: data)
            }
            .edgesIgnoringSafeArea([.bottom])
        }
        .navigationTitle(essentialsChapter17NavigationTitle)
        .navigationBarTitleDisplayMode(.inline)
    }
    //タップ後に遷移先へ遷移させる関数
    func containedViewiOSApp17DevelopmentEssentialsCh17(dataiOSApp17DevelopmentEssentialsCh17: ListiOSApp17DevelopmentEssentialsCh17) -> AnyView {
        switch dataiOSApp17DevelopmentEssentialsCh17.view {
        case .Sec1:
            return AnyView(NavigationLink (destination: Essentials17()) {
                Text(dataiOSApp17DevelopmentEssentialsCh17.title)
            })
        }
    }
}
#Preview {
    iOSApp17DevelopmentEssentialsCh17()
}
//Essentials17.swift
struct Essentials17: View {
    var body: some View {
        VStack{
            TabView {
                Essentials17Code()
                    .tabItem {
                        Image(systemName: codeImageTab)
                        Text(codeTextTab)
                    }
                Essentials17Points()
                    .tabItem {
                        Image(systemName: pointImageTab)
                        Text(pointTextTab)
                    }
                Essentials17WEB()
                    .tabItem {
                        Image(systemName: webImageTab)
                        Text(webTextTab)
                    }
            }
        }
    }
}
#Preview {
    Essentials17()
}
struct Essentials17Code: View {
    var body: some View {
        ScrollView{
            Text(codeEssentials17)
        }
    }
}
#Preview {
    Essentials17Code()
}
struct Essentials17Points: View {
    var body: some View {
        ScrollView{
            Text(pointEssentials17)
        }
    }
}
#Preview {
    Essentials17Points()
}
struct Essentials17WebView: UIViewRepresentable {
    let searchURL: URL
    func makeUIView(context: Context) -> WKWebView {
        let view = WKWebView()
        let request = URLRequest(url: searchURL)
        view.load(request)
        return view
    }
    func updateUIView(_ uiView: WKWebView, context: Context) {
        
    }
}
struct Essentials17WEB: View {
    private var url:URL = URL(string: urlEssentials17)!
    var body: some View {
        Essentials17WebView(searchURL: url)
    }
}
#Preview {
    Essentials17WEB()
}
//タイトル
let essentialsChapter17NavigationTitle = "第17章"
let essentialsChapter17Title = "第17章 SwiftUI モードでのXcode15の使用"
let essentialsChapter17SubTitle = "第1節 SwiftUIモードでのXcode15の使用"
//コード
let codeEssentials17 = """
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}
#Preview {
    ContentView()
}

struct SubView: View {
    var body: some View{
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("こんにちは、SwiftUI🥺")
                .font(.title)
            Text(/*@START_MENU_TOKEN@*/"おはこんばんちは、アラレちゃん"/*@END_MENU_TOKEN@*/)
                .font(.largeTitle)
                .fontWeight(.bold)
                .foregroundColor(Color.red)
        }
        .padding()
    }
}
#Preview{
    SubView()
}
"""
//ポイント
let pointEssentials17 = """
1 マルチプラットフォーム=複合的に対応した開発環境なので
・iOS
・WatchOS
・MacOS
・tvOS
にも対応してる。
しかも、最小限のコードの変更で、
最初はiOSなんかで作ったプロジェクトを別のOSに簡単に変更できる

2 画面の構成としては、
・A:プロジェクトナビゲーター = プロジェクト内のファイルを管理
・B:コードエディター = 実際に組み込む作業をする
・C:プレビューキャンパス = シミュレータや実機を使わずに動作検証できる
・D:アトリビュートインスペクター = 色やサイズ各状態などをコードを打たずに編集できる
・E:コンソールエリア = 実行時にPrintなんかで処理を見れる
3 各エリアは自分で使いやすいようにカスタマイズ可能
4 Canvasの構成
・A:キャンバスエリア = 現在のビューを表示する
・B:サイズボタン = 表示の拡大や縮小、100%なんかにする
・C:ピンボタン = 同じファイルに複数のプレビューなんかが
・D:プレビューツールバー = プレビューの詳細機能切り替え
さらに詳細機能としては、
・A:ライブモード = シミュレーターとか実機を使わずに実際の動きを確認
・B:選択モード = ライブではなくあくまでもビュー単体で確認
・C:バリアントボタン = 色合いとか文字サイズなんかを切り替え
・D:ローテートボタン = 縦向きや横向きなどを切り替え
・E:デバイス切り替え = iPhoneやiPadなんかの各機種を選択する
5 経験談:
⒈AutoLayoutって概念を考えなくてよくなった
⒉ライブビューでやってるのに、想定してる動きにならない
👉自分の組み方が何かおかしいんだろうか?
って考えて、コードと睨めっこしてうんうん唸るより先に、シミュレーターや実機で動かしてみてね。
6 SwiftUIで作業するってことは、
・ビュー追加
・モディファイアを使ったロジックを追加
・双方向性な宣言と他のデータインスタンスへの結びつけ
👉コードエディターの中でモディファイアと構築でやっていける
7 モディファイアとは?いい感じにする!ってイメージ

8 詳細を確認したいときは、Jump to Definitionを使う

9シミュレーター
・A:停止ボタン = 実行中のシミュレーターを停止
・B:実行ボタン = 作ったアプリをシミュレーターで実行
・C:デバイス選択メニュー = シミュレーターで実行したい機種なんかを選択
・D:Xcodeツールバー = Xcodeの状態を表示
でシミュレーター実行中に使える機能も沢山ある。

10 シミュレーター実行中に階層構造も確認できる機能もある
"""

//URL
let urlEssentials17 = "https://note.com/m_kakudo/n/n4147d790c501"

この記事が気に入ったらサポートをしてみませんか?