Swift4.2 配列の変化と読み込みと保存の話 ?

# Swift4.2 今回は ? なんだろう ?
2019/02/26

2/27・配列要素で以下の変化を追加しました

- インサート
- 追加
- 削除
- 入れ替え 等

```インサート.swift

        dataList.insert("2,ソニー,56インチ4Kテレビ", at: 2)
print("\n通過・2番目をシャープからソニーに変更しました -> \(dataList)")

```

```追加.swift

        dataList.append("6,配列の最後に,追加しました")
print("\n通過・配列の最後に追加しました -> \(dataList)")

```

```削除.swift

        dataList.remove(at: 2)

```

```入れ替え.swift

        dataList.swapAt(1, 2)
print("\n通過・1番目と2番目を入れ替えます -> \(dataList)")

```


> 目的・csvファイルをバンドルします、起動時にcsvファイルを読み込みます、配列の変化を楽しみます、csvファイルを外部に保存する為にサブフォルダを作成します、csvファイルを保存します、次からの起動では外部のcsvファイルを読み込みます

- 外部ファイルとは ?

> iPadとかならばアプリのファイル内の「このiPad内」のアプリ名のフォルダ内に作成した「NewFolder」の中にリスト0.csvが保存されてるはずですよ ?

> 配列の変化とは ?

- ["0,メーカー,名称"]を
- ["0", "メーカー", "名称"]にして
- ["0,メーカー,名称"]に戻しています

> 私の場合はstoryboardの部品のSegmented ControlのタイトルやSegmentの内容などに利用しています

```配列.swift

//
//  ViewController.swift
//  csvData
//
//  Created by 福田敏一 on 2019/02/26.
//  Copyright © 2019 福田敏一. All rights reserved.
//

import UIKit

var newData0: [String] = []
var newData1: [String] = []
var dataList: [String] = []
var dataDetail: [String] = []
var dataDetail0: [String] = []
var 最初を取り出す: [String] = []
var Array2: [[String]] = [[],[]]
var 更に1番目を取り出す: String = ""
var 更に2番目を取り出す: String = ""
var userPath:String!
var path: String = ""
var csvData: String = ""

class ViewController: UIViewController {
    
//使用しているのは「リスト0」と「NewFolder」だけです、必要なら「リスト1」と「リスト2」をバンドル追加します
    var 書類の種類 = ["リスト0","リスト1", "リスト2", "NewFolder"]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        loadCSV(書類1: 0, 書類2: 3)
        配列の編集()
        makeDirector(director: 書類の種類[3])
        saveCSV(書類1: 0, 書類2: 3)
    }
    func loadCSV(書類1: Int, 書類2: Int) {
//To Class・LoadCSVsingle
        let 読込: LoadCSVsingle = LoadCSVsingle()
        読込.CSV読込Single(計算書の種類: 書類の種類[書類1], director: 書類の種類[書類2])
    }
    func 配列の編集() {
//print("通過・Array2[0] -> \(Array2[0])")
//print("通過・Array2[1] -> \(Array2[1])")
//print("通過・Array2 -> \(Array2)")

print("\n通過・dataList -> \(dataList)")
//Array＜String＞とStringの追加
        dataList.append("6,配列の最後に,追加しました")
print("\n通過・配列の最後に追加しました -> \(dataList)")
        
        dataList.remove(at: 6)
print("\n通過・6番目を削除しました -> \(dataList)")
        
        let 変更の準備 = dataList[2]
        dataList.remove(at: 2)
        dataList.insert("2,ソニー,56インチ4Kテレビ", at: 2)
print("\n通過・2番目をシャープからソニーに変更しました -> \(dataList)")
        
        dataList.remove(at: 2)
        dataList.insert(変更の準備, at: 2)
print("\n通過・2番目をUndoしました -> \(dataList)")
        
        dataList.swapAt(1, 2)
        print("\n通過・1番目と2番目を入れ替えます -> \(dataList)")
        
        let dataListの最初を取り出す: [String] = [dataList[0]]
print("\n通過・dataListの最初を取り出す -> \(dataListの最初を取り出す)")
        
        var dataDetail1: [String] = []
//カンマでデータを分割して配列に格納する。
        for i in 0..<dataListの最初を取り出す.count {
            dataDetail = String(describing: dataListの最初を取り出す[i]).components(separatedBy: ",")
//Array＜String＞とArray＜String＞の追加
            dataDetail1 += dataDetail
        }
print("\n通過・カンマでデータを分割・dataDetail1 -> \(dataDetail1)")
        let dataDetail1String: [String] = [dataDetail1.joined(separator: ",")]
print("\n通過・dataListの最初を取り出すに戻す・dataDetail1String -> \(dataDetail1String)\n")
    }
    func makeDirector(director: String) {
//To Class・MakeDirector
        let 作成: MakeDirector = MakeDirector()
        作成.ディレクトリ作成(director: director)
    }
    func saveCSV(書類1: Int, 書類2: Int) {
//To Class・SaveCSVsingle
        let 保存: SaveCSVsingle = SaveCSVsingle()
        保存.保存CSVSingle(計算書の種類: 書類の種類[書類1], director: 書類の種類[書類2])
    }
}

class LoadCSVsingle: UIViewController {
    let fileManager = FileManager()
    
    func CSV読込Single(計算書の種類: String, director: String) {
        newData0 = []
        newData1 = []
        
        do {
//ユーザーが保存したCSVファイルのパス
            userPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/" + director + "/" + 計算書の種類 + ".csv"
            path = userPath
//print("通過・pathの型 -> \(type(of: path))")
//print("通過・path -> \(path)")
            if (fileManager.fileExists(atPath: path) == false) {
//ユーザーが保存したCSVファイルが無い場合は、初期CSVファイルから読み込む。
                path = Bundle.main.path(forResource: 計算書の種類, ofType: "csv")!
            }
//CSVファイルのデータを取得する。
            csvData = try String(contentsOfFile:path, encoding:String.Encoding.utf8)
print("\n通過・class LoadCSVsingle・csvData -> \(csvData)")
            //改行区切りでデータを分割して配列に格納する。
            dataList = csvData.components(separatedBy: "\n")
//print("通過・class LoadCSVsingle・dataList -> \(dataList)")
            dataDetail0 = csvData.components(separatedBy: "\n")
//print("\n通過・dataDetail0 -> \(dataDetail0)")
            if dataDetail0.last == "" {
                dataDetail0.removeLast()
            }
            for i in 0..<dataDetail0.count {
                最初を取り出す = dataDetail0[i].components(separatedBy: ",")
//print("通過・最初を取り出す -> \(最初を取り出す)")
                更に1番目を取り出す = 最初を取り出す[1]
                更に2番目を取り出す = 最初を取り出す[2]
                newData0.append(更に1番目を取り出す)
                newData1.append(更に2番目を取り出す)
            }
            Array2[0] = newData0
            Array2[1] = newData1
            if dataList.last == "" {
                dataList.removeLast()
            }
        } catch {
            print(error)
        }
    }
    
    /*
     // MARK: - Navigation
     
     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     // Get the new view controller using segue.destinationViewController.
     // Pass the selected object to the new view controller.
     }
     */
    
}
class MakeDirector: UIViewController {
    
    func ディレクトリ作成(director: String) {
//ディレクトの作成
        let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/" + director
//print("通過・class MakeDirector path -> \(path)")
        do {
//ディレクトリが存在するかどうかの判定
            if !FileManager.default.fileExists(atPath: path) {
//ディレクトリが無い場合ディレクトリを作成する
                try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: false , attributes: nil)
            }
        } catch {
            // エラー処理
        }
    }
    
    /*
     // MARK: - Navigation
     
     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     // Get the new view controller using segue.destinationViewController.
     // Pass the selected object to the new view controller.
     }
     */
    
}
class SaveCSVsingle: UIViewController {
//ファイルシステムの内容に便利なインタフェースを提供するオブジェクト
    let fileManager = FileManager()
    
    func 保存CSVSingle(計算書の種類: String, director: String) {
//改行区切りで配列を連結する。
        let outputStr = dataList.joined(separator: "\n")
        
        do {
//ユーザーが保存したCSVファイルのパス
            userPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/" + director + "/" + 計算書の種類 + ".csv"
            if(outputStr == "") {
                //配列が空の場合はユーザーが保存したCSVファイルを削除する。
                try fileManager.removeItem(atPath: userPath)
            } else {
//ファイルを出力する。
                try outputStr.write(toFile: userPath, atomically: false, encoding: String.Encoding.utf8 )
            }
        } catch {
            print(error)
        }
        print("通過・class SaveCSVsingle・userPath -> \(userPath!)")
    }
    
    /*
     // MARK: - Navigation
     
     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     // Get the new view controller using segue.destinationViewController.
     // Pass the selected object to the new view controller.
     }
     */
    
}

//実行結果

通過・class LoadCSVsingle・csvData -> 0,メーカー,名称
1,Apple,iPad Air2
2,シャープ,42インチテレビ
3,飯島商店,ももジャム
4,イチビキ,生国産しょうゆ450ml
5,ハマダ食品,大人のプレミアム


通過・dataList -> ["0,メーカー,名称", "1,Apple,iPad Air2", "2,シャープ,42インチテレビ", "3,飯島商店,ももジャム", "4,イチビキ,生国産しょうゆ450ml", "5,ハマダ食品,大人のプレミアム"]

通過・配列の最後に追加しました -> ["0,メーカー,名称", "1,Apple,iPad Air2", "2,シャープ,42インチテレビ", "3,飯島商店,ももジャム", "4,イチビキ,生国産しょうゆ450ml", "5,ハマダ食品,大人のプレミアム", "6,配列の最後に,追加しました"]

通過・6番目を削除しました -> ["0,メーカー,名称", "1,Apple,iPad Air2", "2,シャープ,42インチテレビ", "3,飯島商店,ももジャム", "4,イチビキ,生国産しょうゆ450ml", "5,ハマダ食品,大人のプレミアム"]

通過・2番目をシャープからソニーに変更しました -> ["0,メーカー,名称", "1,Apple,iPad Air2", "2,ソニー,56インチ4Kテレビ", "3,飯島商店,ももジャム", "4,イチビキ,生国産しょうゆ450ml", "5,ハマダ食品,大人のプレミアム"]

通過・2番目をUndoしました -> ["0,メーカー,名称", "1,Apple,iPad Air2", "2,シャープ,42インチテレビ", "3,飯島商店,ももジャム", "4,イチビキ,生国産しょうゆ450ml", "5,ハマダ食品,大人のプレミアム"]

通過・1番目と2番目を入れ替えます -> ["0,メーカー,名称", "2,シャープ,42インチテレビ", "1,Apple,iPad Air2", "3,飯島商店,ももジャム", "4,イチビキ,生国産しょうゆ450ml", "5,ハマダ食品,大人のプレミアム"]

通過・dataListの最初を取り出す -> ["0,メーカー,名称"]

通過・カンマでデータを分割・dataDetail1 -> ["0", "メーカー", "名称"]

通過・dataListの最初を取り出すに戻す・dataDetail1String -> ["0,メーカー,名称"]

通過・class SaveCSVsingle・userPath -> /Users/papassan/Library/Developer/CoreSimulator/Devices/DC475489-9C34-46A5-9967-7222755811D8/data/Containers/Data/Application/8B5F0CAE-DA47-4679-92E1-57D7D92B61CC/Documents/NewFolder/リスト0.csv

```

- リスト0.csv これをプロジェクトにバンドルしてください

```csvファイル.swift

0,メーカー,名称
1,Apple,iPad Air2
2,シャープ,42インチテレビ
3,飯島商店,ももジャム
4,イチビキ,生国産しょうゆ450ml
5,ハマダ食品,大人のプレミアム


```

ここまで