メインコンテンツへスキップ
見出し画像

【じっくりSw1ftUI 27】Essentials第14章〜Playgroundで遊ぼう13〜配列と辞書 (ディクショナリ)①配列 実は既にコードテンプレートで使ってる🌱

    さてと、シンタックス(基本文法)編も残すところあと2章
    今月中には終わりそうかな💦
    今回は、値を管理する

    配列と辞書(ディクショナリ)

    をやってくんだけど、これって実は、いつも記事公開後にやってる

    のコード

    //各項目に表示する文字列
    let dataiOSApp17DevelopmentEssentials: [ListiOSApp17DevelopmentEssentials] = [
        ListiOSApp17DevelopmentEssentials(id: 1, title: "第1章", view: .Ch1),
        //じっくり13で追加
        ListiOSApp17DevelopmentEssentials(id: 2, title: "第2章", view: .Ch2),
        //じっくり13で追加
        ListiOSApp17DevelopmentEssentials(id: 3, title: "第3章", view: .Ch3)
    ]

    なんかで既にやってる感じ👀💦

    去年の10月からこのマガジンの記事を

    ①導入編
    ↓
    ②文法編
    👈イマココ!
    ↓
    ③実践編

    て感じで進めてたのは、

    単純に基本文法だけをやりました = 1を教えた
    だから後は、自分たちで理解してるならできるようになれ!
    👉1を聞いて10を理解しろ!

    なんてサンプルコードや実際に動くもので

    どう繋がっているかを示しもせずにべき論で片付けるのは、乱暴すぎるから
    👉人に何かを伝える時は、「やってみて、言って聞かせてさせてみて、褒めてやらねば人は動かじ」(山本五十六)で、きちんとつながりを見せてあげないと、本当の理解は進まない

    からね👀

    ま、だから1を聞いて10を理解しろの弊害を、

    で書いてはいるけどね〜〜〜〜!こんなことをいくら書いたところで、

    「そーなるとは限らない」って思い込みで、経験者のゆーことを否定

    する人は、何をどーしようと

    同じ歴史を繰り返す

    だけだから

    知ったこっちゃない

    し、オイラは別に自分の学び直しを記事にして公開してるだけで、別に先生とか教育ビジネスでやってるわけじゃないから、別に誰かの先生になったつもりもないし。

    今回も、オイラの学びなんか知らん!関係ない、必要ないって人は、

    に本文はサンプルコードも含めてそのまま載ってるみたいだから、そちらでどうぞ🕺

    さてと、じっくり第14章を読んでく

    まずは概要

    いくつかのオブジェクトをひとつに含めることができる=コレクション

    の基礎である

    配列と辞書

    を紹介するぜって感じのことを書いてるね

    でコレクションには、

    計算できるコレクションと計算できないコレクションがある
    👉要は、どっちもいける

    ってことを説明していて、ま、要は

    コレクション=複数の値をひとつに格納できる

    てことで、

    配列の構文

    var array: [arrayType] = [value1, value2, value3,,,]

    て感じで、

    []で複数の値を囲むだけ

    ってイメージ

    じゃ、実際に〜〜〜〜今回はフルーツで

    //型指定なし
    var fruitsBaskets14_1 = ["りんご","バナナ","葡萄","苺"]

    てな感じで、型指定をつける場合は

    //型指定あり
    var fruitsBaskets14_2:[String] = ["りんご","バナナ","葡萄","苺"]

    てな感じ。

    画像

    でもって、これをまずはインスタンスとして宣言する場合は〜〜〜

    値を持たせちゃダメ

    らしく、

    //インスタンス
    var fruitsBaskets14_3 = [String]()
    var fruitsPrices14_4 = [Float]()

    みたいな感じにしないといけないみたいね👀💦

    インスタンスに初期値を設定する場合は〜〜

    //インスタンスに初期値を設定
    var fruitsBaskets14_5 = [String](repeating: "りんご", count: 3)

    てな感じで設定するみたいだね👀でコイツを実行すると〜〜〜

    画像
    実行できてんね👀

    他にも

    //型指定なし
    var fruitsBaskets14_1 = ["りんご","バナナ","葡萄","苺"]
    //型指定あり
    var fruitsBaskets14_2:[String] = ["メロン","パイナップル","柿","西瓜"]

    てな感じに変更して

    //配列を結合
    var fruitBaskets14_6 = fruitsBaskets14_1 + fruitsBaskets14_2
    //実行
    print(fruitBaskets14_6.self)

    で実行すると

    画像
    てな感じで実行できてるね

    てことは面白いので〜〜〜

    //型指定なし
    var fruitsBaskets14_1 = ["🍏","🍌","🍇","🍓"]
    //型指定あり
    var fruitsBaskets14_2:[String] = ["🍈","🍍","🍋","🍉"]//柿だけレモンに変更

    して、さっきのコマンドを実行すると〜〜〜

    画像
    かわゆす🥺

    なんてこともできちゃうね👀だって、

    絵文字も文字=String

    だから🕺

    さてと、脱線はこのくらいにして先に進む〜〜〜

    次は制御文=条件分岐を例に

    //条件分岐
    if fruitsBaskets14_3.isEmpty {
        print("値が何もないぞ👀")
    } else {
        print("値があるぞ👀")
    }

    を実行してあげて

    画像
    てな感じのこともできるし

    どれかの値にアクセス(呼び出し)するなら

    //りんごにアクセス
    print(fruitsBaskets14_1[0])
    //バナナにアクセス
    print(fruitsBaskets14_1[1])
    画像
    てな感じでアクセスできる

    ここでポイント①

    配列の数え方(位置)は、プログラミング言語によりけりなんだけど、

    左から0始まり : 左から1個目が0 👈 Swiftとか最近のはこっち
    左から1始まり : 左から1個目が1 
    👈  COBOLとかはたしかこっち

    て違いがあるから気をつけてね👀

    シャッフルや〜〜〜(「劇場版賭博黙示録カイジ」の山本太郎ではないぞ👀)

    //シャッフル
    let shuffledFruitsBaskets14_7 = fruitBaskets14_6.shuffled()
    print(shuffledFruitsBaskets14_7.self)
    画像
    順番ぐちゃぐちゃ 藁🤣

    これって結構、くじ引きゲームとかで使えそう💦

    さらにランダムに〜〜〜

    //ランダム
    let randomFruitsBaskets14_8 = shuffledFruitsBaskets14_7.randomElement()
    print(randomFruitsBaskets14_8.self)
    画像
    実行1回目👀🍉ちゃんが出た
    なぜかオプショナルに、、、
    //ランダム
    let randomFruitsBaskets14_8 = shuffledFruitsBaskets14_7.randomElement()
    print(randomFruitsBaskets14_8!.self)//強制アンラップして〜〜
    画像
    2回目の実行をすると、🍍ちゃんが出た

    アンラップしないと何回実行しても〜〜〜

    画像
    てな感じでOptionalが消えないので〜〜〜

    どう出したいかにはよるけど、消したい時はしっかりアンラップを忘れないでね🕺

    要素に桃を追加

    //要素に桃を追加
    fruitsBaskets14_2 += ["🍑"]
    //実行
    print(fruitsBaskets14_2.self)
    画像
    やはり桃は大好物です🤤
    //結合のやつをまんま実行
    print(fruitBaskets14_6.self)
    画像
    もちろん追加する前に結合してるから🍑ちゃんはいません
    //結合し直してあげる
    let combinedFruits14_9 = fruitsBaskets14_1 + fruitsBaskets14_2
    print(combinedFruits14_9.self)
    画像
    🍑ちゃんも仲間になれた

    ここでポイント②

    要素の追加をした後は、どっちの値を結果として出したいのか
    で処理の順序を変える
    👉追加前のままでいいか、追加後を含めたいか

    さてと、次はりんごとバナナの間にもう一個🍑入れてみよう

    //結合し直してあげる
    let combinedFruits14_9 = fruitsBaskets14_1 + fruitsBaskets14_2
    print(combinedFruits14_9.self)
    //りんごとバナナの間にもう一個🍑入れてみよう
    combinedFruits14_9.insert("🍑", at: 1)
    print(combinedFruits14_9)

    で実行すると〜〜〜実は

    画像
    てな感じでエラーになる👀

    ここでポイント③

    理由は簡単で、

    let = 定数で定義しているから

    配列に関しても、その後も変更される可能性がある場合は、

    基本、変数=varで定義してあげる

    ま、よくJavaScriptの教科書

    なんかでは、

    「スコープはなるべく狭くして、グローバルな引数は使わない。変更がないものはletで以外は、varで書く。」

    なんて書いてるのを鵜呑みにして、

    オブジェクト志向言語の旨みを理解してないのか
    教科書通りに何でもかんでも
    自分が作る時点では変更可能性がないからletで書く

    人が多いんだけど、処理に関するコードの引数を定数でやっちゃうと

    オブジェクト志向言語は短いコードを再利用してどこで呼び出している
    👉結合が強くなる=密結合

    ので、

    後から定数から変数に変えればいいや

    でやってしまうと、、、

    他の処理に影響を与えて、他の処理が狂う

    なんてことが出てくる結果、最初から変数でしかもグローバルに定義しておけばひとつで済む同じ役割しかしてない引数を結局、下手に扱えないから10個も20個もひとつのプロジェクトに定義してしまうなんてザラ

    👉リファクタリング=コードを小分けにして読みやすくする作法なはずが、
    何でもかんでも小分けにして、全体を意識してコンストラクションを考えないから、結局、読みにくいだけのスパゲッティコードにしかならない。
    処理時間も同じような引数が多く、コンパイラの判断に時間がかかり長くなる。

    なんてことが起きるからね。ま、そこらへんの作法については、

    でしっかり感想文形式でまとめてるから興味がある人はそちらも読んでみてね(基本、無料で公開してます!)

    なので、オイラが導入編なんかで作ったコードテンプレートなんかで記事公開後にやってるものも、

    URLManageFile

    let urlEssentials13 = "https://note.com/m_kakudo/n/n57888b472cc4"

    なんかで、

    今後変わることがないものは別ファイルに分けて、
    let文でグローバルに定義=パラメータ化

    してあげてる次第。

    一度公開した記事のURLだけは今後も中々変わることがないからね
    (もし変わったら、変わったときに引数名ではなく、””の中身を変えてあげればいいだけの話)
    👉コード管理の手法

    と、ここはかなり重要なポイントなので、長文になってしまったけど、本題に戻って、

    //結合し直してあげる
    var combinedFruits14_9 = fruitsBaskets14_1 + fruitsBaskets14_2
    print(combinedFruits14_9.self)
    //りんごとバナナの間にもう一個🍑入れてみよう
    combinedFruits14_9.insert("🍑", at: 1)
    print(combinedFruits14_9)

    で

    letをvarにだけ変更してあげて〜〜〜

    画像
    てな感じでしれっと2個目に🍑ちゃんが追加されました🕺

    で、🍑ちゃんが2個はいらないので一個削除したいときは〜〜

    //最後の🍑を削除
    combinedFruits14_9.removeLast()
    print(combinedFruits14_9)
    画像
    てな感じで削除もできる

    または、さっき追加🍑ちゃんもいらないなら、

    //さっきの🍑も削除
    combinedFruits14_9.remove(at: 1)
    print(combinedFruits14_9)
    画像
    てな感じで削除もできる〜〜〜

    繰り返し文を使って反復

    //反復
    for fruits in combinedFruits14_9 {
        print(fruits)
    }

    てな感じで、引数を使って〜〜〜

    画像
    てな感じでもできるし

    桃に全部一気に変えたいなら

    //いったん全要素を削除
    combinedFruits14_9.removeAll()
    print(combinedFruits14_9)
    画像
    てな感じで〜〜〜
    //8個の要素を追加
    for n in 0...8 {
        combinedFruits14_9.insert("🍑", at: 0)
        print(combinedFruits14_9.self)
    }
    画像
    てな感じで追加できた〜〜〜

    プログラミングの基本は、上から下に処理は流すだけなので、最後の結果だけ分かればいいなら

    //8個の要素を追加
    for n in 0...8 {
        combinedFruits14_9.insert("🍑", at: 0)
    }
    print(combinedFruits14_9.self)

    て感じで

    画像
    でもいいしね

    ここでポイント④

    今までの処理で、

    追加/挿入/削除/繰り返し

    で結構、配列の値を変更してしまっているんだけど、みて貰えばわかるけど、オイラは、

    結合後の配列しか使ってないよね?

    これはなぜかと言えば、

    結合元の配列さえ残しておけば、すぐに元に戻すことができるから

    よくこれってDB(データベース)なんかでもしくる人が多いんだけど、

    処理の対象元に直接、やってバックアップなんかも取ってないと戻せなくなる
    👉更新後に涙目😭

    みたいなね
    今回も大元の配列はそのまま残して、全部🍑ちゃんにまで変更してるけど、

    //いったん全要素を削除
    combinedFruits14_9.removeAll()
    //元に戻す
    combinedFruits14_9 = fruitsBaskets14_1 + fruitsBaskets14_2
    print(combinedFruits14_9)

    てな感じで、実行してあげると

    画像
    はい、普通に元通り
    ま、間に今までで🍑ちゃんを追加してるコードがあるから🍑は追加されてるが藁🤣

    大元の配列を直接扱わない
    👉変更とか削除用の配列にミラーしてあげるだけでOK

    繰り返しには他にも〜〜〜

    //キーワードを使って
    combinedFruits14_9.forEach{
        print($0)
    }
    画像
    てな感じのこともできちゃう

    これはさっきの

    //反復
    for fruits in combinedFruits14_9 {
        print(fruits)
    }

    とやってることは同じなんだけど、

    //キーワードを使って
    combinedFruits14_9.forEach{
        print($0)
    }

    と見比べて、

    どちらが第三者が見て見やすいか、職人っぽくってかっちょ良いか

    だけの違い。

    • プロジェクトで安全に管理したい、保守性を高めたい=前者

    • 自分できてます感とか、これくらいは読めて当たり前感を出したい=後者

    くらいな違いかな🧐ま、オイラなら

    動かさなくてもわかるコード=読みやすいシンプルなコード

    にしたいので、前者を使うけどね。

    型を混在させた配列

    //八百屋
    var yaoya14_10:[Any] = ["🍏",123]
    var yaoya14_11:[Any] = ["🍏",123,"🍌",200]
    var yaoya14_12:[Any] = ["🍏","🍌",123,200]
    //繰り返しで出力
    yaoya14_12.forEach{
        print($0)
    }
    for item in yaoya14_12 {
        print(item)
    }

    てな感じで、型をAnyにしてしまえば、

    画像
    実行後

    てな感じでできなくはないんだけど、流石にここまで来ると、

    • 2次元配列

    • 辞書

    なんかでまとめてあげた方がコレクションとしては処理がしやすいんじゃないか?
    こんなん使うのか?

    とは思うんだけど、、、

    ここでポイント⑤

    • 「クライアントさんなんて、DBとか配列なんてよくわかってない」

    • 「まだここの値段が決まってないんだけど、先にアプリを作って欲しい」

    なんかで

    こんなデータをCSVやLogなんかで出して要求してくるなんてザラ

    だから、

    応急的にやる時にはAnyを使うパターンもある
    ↓
    規則性が分かってから、データを整理してわかりやすい配列や辞書にしてあげる

    でやれば良いだけだからね。

    キャスト(as)なんかを下手にAny型の配列で使うと

    //キャスト〜〜〜
    for item in yaoya14_12 {
        print(item as!Int * 100)
    }
    画像
    ま、当たり前っちゃあ当たり前なんだけど、Stringが混在してるからエラー 藁🤣

    なので、

    ここでポイント⑥

    以前から何回も他の記事で書いてるんだけど、

    頭の中だけでコードは書かずに、
    必ずコードを書いたら想定通りに動かした方がいい

    って推奨してる話。

    複雑なコードを書いて、検証もせずに、リリースして後に気づいた涙目😢
    その時には、他でも同じように検証もちゃんとしないゴミコードの温床になっている
    ↓
    改修にめっちゃ時間がかかって納期に間に合いません😭
    数億円の予算をかけてちゃんと検証しなかったばかりにリリース後も誰も使いません😭
    👉=接触確認アプリCOCOA

    みたいなことになった国が2年くらい前にあったような、、、

    になるからね。

    どんな簡単だと思うコードも書いたらまずは検証しよう!

    さてと、配列に関しては以上なんだけど、気がつけば、

    すでにここでポイントも6つになっていて、

    今回は前半だけでかなり内容が濃ゆくもなっているので、

    今回はここまで!

    あとは辞書(ディクショナリ)の話に入っていくだけだし、配列の理解が前提で少し毛色が違う話になるので、そこは次回にしよ🕺

    ま、今回のコードでやりたい人はじっくり復習しておいてね!

    今回のコード(まとめ)

    /**:-------------------
     Essentials 第14章 配列と辞書
     ---------------------*/
    //型指定なし
    var fruitsBaskets14_1 = ["🍏","🍌","🍇","🍓"]
    //型指定あり
    var fruitsBaskets14_2:[String] = ["🍈","🍍","🍋","🍉"]
    //インスタンス
    var fruitsBaskets14_3 = [String]()
    var fruitsPrices14_4 = [Float]()
    //インスタンスに初期値を設定
    var fruitsBaskets14_5 = [String](repeating: "りんご", count: 3)
    //実行
    print(fruitsBaskets14_5.count)
    //配列を結合
    var fruitBaskets14_6 = fruitsBaskets14_1 + fruitsBaskets14_2
    //実行
    print(fruitBaskets14_6.self)
    //条件分岐
    if fruitsBaskets14_3.isEmpty {
        print("値が何もないぞ👀")
    } else {
        print("値があるぞ👀")
    }
    //りんごにアクセス
    print(fruitsBaskets14_1[0])
    //バナナにアクセス
    print(fruitsBaskets14_1[1])
    //シャッフル
    let shuffledFruitsBaskets14_7 = fruitBaskets14_6.shuffled()
    print(shuffledFruitsBaskets14_7.self)
    //ランダム
    let randomFruitsBaskets14_8 = shuffledFruitsBaskets14_7.randomElement()
    print(randomFruitsBaskets14_8!.self)//強制アンラップして〜〜
    //要素に桃を追加
    fruitsBaskets14_2 += ["🍑"]
    //実行
    print(fruitsBaskets14_2.self)
    //結合のやつをまんま実行
    print(fruitBaskets14_6.self)
    //結合し直してあげる
    var combinedFruits14_9 = fruitsBaskets14_1 + fruitsBaskets14_2
    print(combinedFruits14_9.self)
    //りんごとバナナの間にもう一個🍑入れてみよう
    combinedFruits14_9.insert("🍑", at: 1)
    print(combinedFruits14_9)
    //最後の🍑を削除
    combinedFruits14_9.removeLast()
    print(combinedFruits14_9)
    //さっきの🍑も削除
    combinedFruits14_9.remove(at: 1)
    print(combinedFruits14_9)
    //反復
    for fruits in combinedFruits14_9 {
        print(fruits)
    }
    //いったん全要素を削除
    combinedFruits14_9.removeAll()
    print(combinedFruits14_9)
    //8個の要素を追加
    for n in 0...8 {
        combinedFruits14_9.insert("🍑", at: 0)
    }
    print(combinedFruits14_9.self)
    //いったん全要素を削除
    combinedFruits14_9.removeAll()
    //元に戻す
    combinedFruits14_9 = fruitsBaskets14_1 + fruitsBaskets14_2
    print(combinedFruits14_9)
    //キーワードを使って
    combinedFruits14_9.forEach{
        print($0)
    }
    //八百屋
    var yaoya14_10:[Any] = ["🍏",123]
    var yaoya14_11:[Any] = ["🍏",123,"🍌",200]
    var yaoya14_12:[Any] = ["🍏","🍌",123,200]
    //繰り返しで出力
    yaoya14_12.forEach{
        print($0)
    }
    for item in yaoya14_12 {
        print(item)
    }
    //キャスト〜〜〜
    //for item in yaoya14_12 {
    //    print(item as!Int * 100)
    //}

    ま、まとめるとたったこれだけのコードなんだけど、実はその間に色々と解説しといた方がいいことがありまくりなので長くなりました🙇‍♂️

    Apple公式

    さてと次回は

    💃この章の後半:辞書(ディクショナリ)をやる〜〜〜🕺

    記事公開後

    ま、いつも通り

    で〜〜〜〜

    画像
    目次タイトルを整理した〜〜〜
    画像
    節の見立ても整理〜〜〜
    画像
    コード
    画像
    ポイント
    画像
    リンク〜〜

    てな感じで、

    コードテンプレートに嵌め込んで、規則正しい統一した作りにして、
    let文で普段から別ファイルでパラメータ化してたから、変更も簡単
    🕺

    コード

    ◆Essentials14_1.swift

    今回のビュー用に新規作成

    import SwiftUI
    import WebKit
    
    struct Essentials14_1: View {
        var body: some View {
            VStack{
                TabView {
                    Essentials14_1Code()
                        .tabItem {
                            Image(systemName: codeImageTab)
                            Text(codeTextTab)
                        }
                    Essentials14_1Points()
                        .tabItem {
                            Image(systemName: pointImageTab)
                            Text(pointTextTab)
                        }
                    Essentials14_1WEB()
                        .tabItem {
                            Image(systemName: webImageTab)
                            Text(webTextTab)
                        }
                }
            }
        }
    }
    
    #Preview {
        Essentials14_1()
    }
    
    struct Essentials14_1Code: View {
        var body: some View {
            ScrollView{
                Text(codeEssentials14_1)
            }
        }
    }
    
    #Preview {
        Essentials14_1Code()
    }
    
    struct Essentials14_1Points: View {
        var body: some View {
            ScrollView{
                Text(pointEssentials14_1)
            }
        }
    }
    
    #Preview {
        Essentials14_1Points()
    }
    
    struct Essentials14_1WebView: 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 Essentials14_1WEB: View {
        private var url:URL = URL(string: urlEssentials14_1)!
        var body: some View {
            Essentials14_1WebView(searchURL: url)
        }
    }
    
    #Preview {
        Essentials14_1WEB()
    }

    ◆iOSApp17DevelopmentEssentialsCh14.swift

    今回のビュー用に新規作成

    import SwiftUI
    
    //ビュー管理構造体
    struct ListiOSApp17DevelopmentEssentialsCh14: Identifiable {
        var id: Int
        var title: String
        var view: ViewEnumiOSApp17DevelopmentEssentialsCh14
    }
    
    //遷移先の画面を格納する列挙型
    enum ViewEnumiOSApp17DevelopmentEssentialsCh14 {
        case Sec1
    }
    
    //各項目に表示するリスト項目
    let dataiOSApp17DevelopmentEssentialsCh14: [ListiOSApp17DevelopmentEssentialsCh14] = [
        ListiOSApp17DevelopmentEssentialsCh14(id: 1, title: essentialsChapter14_1SubTitle, view: .Sec1)
    ]
    
    struct iOSApp17DevelopmentEssentialsCh14: View {
        var body: some View {
            VStack {
                Divider()
                List (dataiOSApp17DevelopmentEssentialsCh14) { data in
                    self.containedViewiOSApp17DevelopmentEssentialsCh14(dataiOSApp17DevelopmentEssentialsCh14: data)
                }
                .edgesIgnoringSafeArea([.bottom])
            }
            .navigationTitle(essentialsChapter14NavigationTitle)
            .navigationBarTitleDisplayMode(.inline)
        }
        //タップ後に遷移先へ遷移させる関数
        func containedViewiOSApp17DevelopmentEssentialsCh14(dataiOSApp17DevelopmentEssentialsCh14: ListiOSApp17DevelopmentEssentialsCh14) -> AnyView {
            switch dataiOSApp17DevelopmentEssentialsCh14.view {
            case .Sec1:
                return AnyView(NavigationLink (destination: Essentials14_1()) {
                    Text(dataiOSApp17DevelopmentEssentialsCh14.title)
                })
            }
        }
    }
    
    #Preview {
        iOSApp17DevelopmentEssentialsCh14()
    }

    ◆iOSApp17DevelopmentEssentials.swift

    今回のビュー用に追加

    import SwiftUI
    
    //ビュー管理構造体
    struct ListiOSApp17DevelopmentEssentials: Identifiable {
        var id: Int
        var title: String
        var view: ViewEnumiOSApp17DevelopmentEssentials
    }
    
    //遷移先の画面を格納する列挙型
    enum ViewEnumiOSApp17DevelopmentEssentials {
        case Ch1
        //じっくり13で追加
        case Ch2
        //じっくり13で追加
        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で追加
        case Ch14
    }
    
    //各項目に表示する文字列
    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で追加
        ListiOSApp17DevelopmentEssentials(id: 14, title: essentialsChapter14Title, view: .Ch14)
    ]
    
    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で追加
            case .Ch14:
                return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh14()) {
                    Text(dataiOSApp17DevelopmentEssentials.title)
                })
            }
        }
    }
    
    #Preview {
        iOSApp17DevelopmentEssentials()
    }

    ◆TitleManageFile.swift

    今回のビュー用に追加

    let urlEssentials14_1 = "https://note.com/m_kakudo/n/nb2031fc09971"

    ◆PointManageFile.swift

    今回のビュー用に追加

    let pointEssentials14_1 = """
    ①配列の数え方(位置)は、プログラミング言語によりけりなんだけど、
    左から0始まり : 左から1個目が0 👈 Swiftとか最近のはこっち
    左から1始まり : 左から1個目が1 👈  COBOLとかはたしかこっち
    て違いがあるから気をつけてね👀
    
    ②要素の追加をした後は、どっちの値を結果として出したいのか
    で処理の順序を変える
    👉追加前のままでいいか、追加後を含めたいか
    
    ③理由は簡単で、
    let = 定数で定義しているから
    配列に関しても、その後も変更される可能性がある場合は、
    基本、変数=varで定義してあげる
    
    ④今までの処理で、
    追加/挿入/削除/繰り返し
    で結構、配列の値を変更してしまっているんだけど、みて貰えばわかるけど、オイラは、
    結合後の配列しか使ってないよね?
    これはなぜかと言えば、
    結合元の配列さえ残しておけば、すぐに元に戻すことができるから
    
    ⑤「クライアントさんなんて、DBとか配列なんてよくわかってない」
    「まだここの値段が決まってないんだけど、先にアプリを作って欲しい」
    なんかで
    こんなデータをCSVやLogなんかで出して要求してくるなんてザラ
    だから、
    応急的にやる時にはAnyを使うパターンもある
    ↓
    規則性が分かってから、データを整理してわかりやすい配列や辞書にしてあげる
    
    ⑥頭の中だけでコードは書かずに、必ずコードを書いたら想定通りに動かした方がいい
    """

    ◆CodeManageFile.swift

    今回のビュー用に追加

    let codeEssentials14_1 = """
    /**:-------------------
     Essentials 第14章 配列と辞書
     ---------------------*/
    //型指定なし
    var fruitsBaskets14_1 = ["🍏","🍌","🍇","🍓"]
    //型指定あり
    var fruitsBaskets14_2:[String] = ["🍈","🍍","🍋","🍉"]
    //インスタンス
    var fruitsBaskets14_3 = [String]()
    var fruitsPrices14_4 = [Float]()
    //インスタンスに初期値を設定
    var fruitsBaskets14_5 = [String](repeating: "りんご", count: 3)
    //実行
    print(fruitsBaskets14_5.count)
    //配列を結合
    var fruitBaskets14_6 = fruitsBaskets14_1 + fruitsBaskets14_2
    //実行
    print(fruitBaskets14_6.self)
    //条件分岐
    if fruitsBaskets14_3.isEmpty {
        print("値が何もないぞ👀")
    } else {
        print("値があるぞ👀")
    }
    //りんごにアクセス
    print(fruitsBaskets14_1[0])
    //バナナにアクセス
    print(fruitsBaskets14_1[1])
    //シャッフル
    let shuffledFruitsBaskets14_7 = fruitBaskets14_6.shuffled()
    print(shuffledFruitsBaskets14_7.self)
    //ランダム
    let randomFruitsBaskets14_8 = shuffledFruitsBaskets14_7.randomElement()
    print(randomFruitsBaskets14_8!.self)//強制アンラップして〜〜
    //要素に桃を追加
    fruitsBaskets14_2 += ["🍑"]
    //実行
    print(fruitsBaskets14_2.self)
    //結合のやつをまんま実行
    print(fruitBaskets14_6.self)
    //結合し直してあげる
    var combinedFruits14_9 = fruitsBaskets14_1 + fruitsBaskets14_2
    print(combinedFruits14_9.self)
    //りんごとバナナの間にもう一個🍑入れてみよう
    combinedFruits14_9.insert("🍑", at: 1)
    print(combinedFruits14_9)
    //最後の🍑を削除
    combinedFruits14_9.removeLast()
    print(combinedFruits14_9)
    //さっきの🍑も削除
    combinedFruits14_9.remove(at: 1)
    print(combinedFruits14_9)
    //反復
    for fruits in combinedFruits14_9 {
        print(fruits)
    }
    //いったん全要素を削除
    combinedFruits14_9.removeAll()
    print(combinedFruits14_9)
    //8個の要素を追加
    for n in 0...8 {
        combinedFruits14_9.insert("🍑", at: 0)
    }
    print(combinedFruits14_9.self)
    //いったん全要素を削除
    combinedFruits14_9.removeAll()
    //元に戻す
    combinedFruits14_9 = fruitsBaskets14_1 + fruitsBaskets14_2
    print(combinedFruits14_9)
    //キーワードを使って
    combinedFruits14_9.forEach{
        print($0)
    }
    //八百屋
    var yaoya14_10:[Any] = ["🍏",123]
    var yaoya14_11:[Any] = ["🍏",123,"🍌",200]
    var yaoya14_12:[Any] = ["🍏","🍌",123,200]
    //繰り返しで出力
    yaoya14_12.forEach{
        print($0)
    }
    for item in yaoya14_12 {
        print(item)
    }
    //キャスト〜〜〜
    //for item in yaoya14_12 {
    //    print(item as!Int * 100)
    //}
    """

    ◆TitleManageFile.swift

    大分ビューも溜まってきたので、ちょっと手直しして追加〜〜〜
    手直しに合わせて、これまでのコードで各章目次の"第1節"ってなってたコードなんかも変えた〜〜〜

    import Foundation
    let essentialsChapter1NavigationTitle = "第1章"
    let essentialsChapter1Title = "第1章 iOS17アプリ開発の基礎の概要"
    let essentialsChapter1SubTitle = "第1節 iOS17アプリ開発の基礎の概要"
    let essentialsChapter2NavigationTitle = "第2章"
    let essentialsChapter2Title = "第2章 AppleDeveloperProgramに参加する方法"
    let essentialsChapter2SubTitle = "第1節 AppleDeveloperProgramに参加する方法"
    let essentialsChapter3NavigationTitle = "第3章"
    let essentialsChapter3Title = "第3章 Xcode15とiOS17SDKのインストール"
    let essentialsChapter3SubTitle = "第1節 Xcode15とiOS17SDKのインストール"
    let essentialsChapter4NavigationTitle = "第4章"
    let essentialsChapter4Title = "第4章 Xcode15プレイグラウンドの概要"
    let essentialsChapter4SubTitle = "第1節 Xcode15プレイグラウンドの概要"
    let essentialsChapter5NavigationTitle = "第5章"
    let essentialsChapter5Title = "第5章 Swiftデータ型、定数、変数"
    let essentialsChapter5SubTitle = "第1節 Swiftデータ型、定数、変数"
    let essentialsChapter6NavigationTitle = "第6章"
    let essentialsChapter6Title = "第6章 Swift演算子と式"
    let essentialsChapter6SubTitle = "第1節 Swift演算子と式"
    let essentialsChapter7NavigationTitle = "第7章"
    let essentialsChapter7Title = "第7章 迅速な制御フロー"
    let essentialsChapter7SubTitle = "第1節 迅速な制御フロー"
    let essentialsChapter8NavigationTitle = "第8章"
    let essentialsChapter8Title = "第8章 Swift Switchステートメント"
    let essentialsChapter8SubTitle = "第1節 Swift Switchステートメント"
    let essentialsChapter9NavigationTitle = "第9章"
    let essentialsChapter9Title = "第9章 Swift の関数、メソッド、クロージャ"
    let essentialsChapter9_1SubTitle = "第1節 ファンクション(function)"
    let essentialsChapter9_2SubTitle = "第2節 クロージャ(closure)"
    let essentialsChapter10NavigationTitle = "第10章"
    let essentialsChapter10Title = "第10章 Swiftオブジェクト指向プログラミングの基礎"
    let essentialsChapter10SubTitle = "第1節 Swiftオブジェクト指向プログラミングの基礎"
    let essentialsChapter11NavigationTitle = "第11章"
    let essentialsChapter11Title = "第11章 Swiftのサブクラス化と拡張機能の概要"
    let essentialsChapter11SubTitle = "第1節 Swiftのサブクラス化と拡張機能の概要"
    let essentialsChapter12NavigationTitle = "第12章"
    let essentialsChapter12Title = "第12章 Swift構造と列挙の概要"
    let essentialsChapter12SubTitle = "第1節 Swift構造と列挙の概要"
    let essentialsChapter13NavigationTitle = "第13章"
    let essentialsChapter13Title = "第13章 プロパティラッパー"
    let essentialsChapter13SubTitle = "第1節 プロパティラッパー"
    let essentialsChapter14NavigationTitle = "第14章"
    let essentialsChapter14Title = "第14章 コレクション:配列と辞書(ディクショナリ)"
    let essentialsChapter14_1SubTitle = "第1節 配列"

    以上。

    さてと、新聞読んで犬の散歩とかトイレ掃除で、
    あとはアナログ生活=デジタルデトックスしよ!
    💃みなさんも良い週末を〜〜〜〜🕺

     
     
    タダの道楽者💫ネガティブなコメント一切お断り 裾野が広がりゃそれで良い 洋書と古典とSwiftをこよなく愛するオッさん👀 色即是空🕺 記事はマガジンの方が読みやすいかな💦 ちょい難とダラダラ💃 無駄な対立軸と課題探し思考は要らんな。 変幻自在➕縦横無尽➕融通無碍🟰天衣無縫

    あなたへのおすすめ