質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.49%

  • Swift

    8908questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    5019questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Thread 1: signal SIGABRT

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 194

watanab_

score 22

追記 1/9

himeji001さんのアドバイス通りやってみたところ
Array1には回数の入ったresultArray1と日付が入ったdateArray1を入れることが出来ました。

しかしSaveViewControllerのViewDidLoadで,取り出しArray2に代入して、cellForRowAtにresultArray2とdateArray2のIndexPath.rowを表示させることがまだ出来ません。(Thread 1: Fatal error: Index out of range)
そもそも、Array2 = [resultArray2, dateArray2]なのでArray2[IndexPath.row]はわかりますが、その中の配列resultArray2、dateArray2に[IndexPath.row]は使えないですよね。それぞれ新しく更新されたデータをcellForRowAtで
cell.textLabel!.text (resultArray2の値)
cell.detailTextLabel!.text(dateArray2の値)
を入れる方法はありますでしょうか。
あと、ViewWillAppearはreloaddataだけでいいのか教えていただきたいです。

そしてスッキリした分かりやすいコードを書くために些細なことでもいいのでアドバイスいただけたら幸いです。

ResultViewController.swift

var resultArray1 = [String]()

    var dateArray1 = [String]()

    var Array1: [[String]] = []

    var date = Date()


...
...
...

@IBAction func record(_ sender: Any) {

        //配列を取り出す
        if (UserDefaults.standard.object(forKey: "save") != nil) {
            Array1 = UserDefaults.standard.object(forKey: "save") as! [[String]]

        }


        //zikanを呼び出す
        zikan()
        //resultArrayに回数を追加
        resultArray1.append(countLabel2.text!)

        Array1 = [resultArray1, dateArray1]

        UserDefaults.standard.set(Array1, forKey: "save")

        print(Array1.description)
        print(resultArray1.description)
        print(dateArray1.description)
    }


    func zikan() {
        //日付のフォーマットを指定する
        let format = DateFormatter()
        format.dateFormat = DateFormatter.dateFormat(fromTemplate: "yMdkHm", options: 0, locale: Locale(identifier: "ja_JP"))

        //日付をStringに変換する
        let sDate = format.string(from: date)
        //日付をdateArrayに入れる
        dateArray1.append(sDate)
    }

SaveViewController.swift

var resultArray2 = [String]()

    var dateArray2 = [String]()

    var Array2: [[String]] = []

...
...
...


 override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

        //Array2にresultArray2とdateArray2を代入
        Array2 = [resultArray2, dateArray2]

        if UserDefaults.standard.object(forKey: "save") != nil {

            Array2 = UserDefaults.standard.object(forKey: "save") as! [[String]]
        }

        print(resultArray2.description)
        print(dateArray2.description)
        print("Array2:", Array2.description)


        }


    override func viewWillAppear(_ animated: Bool) {
            super.viewDidAppear(animated)



        tableView.reloadData()


    }


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return Array2.count
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        cell.textLabel!.text = resultArray2[indexPath.row]
        cell.detailTextLabel!.text = dateArray2[indexPath.row]

        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 40
     }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

        if editingStyle == .delete {
            Array2.remove(at: indexPath.row)

            UserDefaults.standard.set(Array2, forKey: "save")

            tableView.reloadData()
        }
    }

・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・

追記1/9

Array2 = UserDefaults.standard.object(forKey: "save") as! [[String]]のところにThread 1: signal SIGABRTが発生する理由がわかりません。不必要なキャッシュは切ってあります。

var resultArray2 = [String]()

    var dateArray2 = [String]()

    var Array2: [[String]] = []


...
...
...



override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

        if UserDefaults.standard.object(forKey: "save") != nil {

            Array2 = UserDefaults.standard.object(forKey: "save") as! [[String]]
        }


        self.resultArray2 = self.Array2[0]
        self.dateArray2 = self.Array2[1]

        Array2 = [resultArray2, dateArray2]


        //Array2 = [ ["晴れ", "雨", "雪"],
                   //["2019/1/1", "2019/1/2", "2019/1/3"] ]

        print("Array2:", Array2.description)
        print(resultArray2.description)
        print(dateArray2.description)

        }


    override func viewWillAppear(_ animated: Bool) {
            super.viewDidAppear(animated)

        tableView.reloadData()
    }


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return resultArray2.count

    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)


        print("Array2:at cellForRowAt", Array2.description)
        print(Array2.count)
        print(resultArray2.description)
        print(dateArray2.description)

        cell.textLabel!.text = resultArray2[indexPath.row]
        cell.detailTextLabel!.text = dateArray2[indexPath.row]

        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 40
     }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

        if editingStyle == .delete {
            Array2.remove(at: indexPath.row)

            UserDefaults.standard.set(Array2, forKey: "save")

            tableView.reloadData()
        }
    }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

ざっと見、間違いがあります。

Array1 = UserDefaults.standard.object(forKey: "save") as! [String]

これ間違ってますよ。

var resultArray1 = [String]()
var dateArray1 = [String]()

var Array1 = [resultArray1,dateArray1]


とあるので、これを紐解くと、
var Array1 = [[String]()]ですよね?
つまり、Array1は[String]を1個、2個と持っている。
[String]のArrayということになるので、
正しくは、

Array1 = UserDefaults.standard.object(forKey: "save") as! [[String]]

です。
まずそこから直してみましょう。他のコードも見てみます。

[以下追記 1/8]
/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

保存のところのコードがやはりおかしいです。
最初に見なくて申し訳なかったです。

@IBAction func record(_ sender: Any) {
    //zikan、①dateArray1に日付をString型で追加保存
    zikan()
    //配列を取り出す ②もし過去のデータがあるなら、Array1に読み込む
    if (UserDefaults.standard.object(forKey: "save") != nil) {
        Array1 = UserDefaults.standard.object(forKey: "save") as! [String]
    }
    // ③resultArray1にStringを追加保存
    resultArray1.append(countLabel2.text!)
    /*//日付をdateArrayに入れる
    dateArray1.append(sDate)*/
    // ④userdefaultsに再度保存
    UserDefaults.standard.set(Array1, forKey: "save")
}

func zikan() {
        //日付のフォーマットを指定する
        let format = DateFormatter()
        format.dateFormat = DateFormatter.dateFormat(fromTemplate: "yMdkHm", options: 0, locale: Locale(identifier: "ja_JP"))
        //日付をStringに変換する
        let sDate = format.string(from: date)
        //日付をdateArrayに入れる
        dateArray1.append(sDate)
    }

func zikan()に関してはまぁ、置いといて、
@IBOutlet func record() {}に関してですが、
追加記入した、順番と行なっていることを考えてください。
①dateArray1に日付(String型)を追加保存
②もし過去のデータがあるなら、Array1に読み込む
③resultArray1にStringを追加保存
④userdefaultsにArray1を再度保存

データ構造と共に加味すると、

var resultArray1 = [String]()
var dateArray1 = [String]()
var Array1 = [resultArray1,dateArray1]

resultArray1, dateArray1共に、空配列から始まる
(。。。viewdidLoadで読み込んでたらごめんなさい。)
まず、dateArray1に押した時の日付が保存される。
Array1にUserDefaultsから過去のデータが入る
dateArray1にStringを追加保存する
UserDefaultsにArray1を再度保存している。

の流れ、なので、よく見てもらえると、
Array1は他のdateArray1やresultArray1とやり取りを何もしていません。
これではArray1に何かデータが入るはずがありません。
なので、何も保存されないのです。

正しい流れは、まず、何と言っても

①過去データがあれば読み込む
userdefaults->Array1
②Array1の中身を分解し、追加できるようにセットする
Array1 -> dateArray1とresultArray1に挿入。
③それぞれのdateArray1とresultArray1にデータを追加
④新規データが追加されたdateArray1とresultArray1を再びArray1にセット(戻す)
⑤Array1を永続させるためにUserdefaultsに上書きする
(⑥printでArray1の中身を確認する)

です。
これでArrayにまず初期データがきちんとできると思います。
printで作ったあとは確認してくださいね。

/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
1/9追記

②がないと、過去のデータが読み込まれないので、
その都度、ボタンを押した時に入れた新しいもののみしか保存されません。
なので、永遠に1個しかデータは保存されません。

なので②は

self.resultArray1 = self.Array1[0] // Array1の要素0(resultArray1の保存したもの)をresultArray1に入れる
// Array1つまり、Userdefaultsから保存したものを取り出して、セットした配列ですよ!
self.dateArray1 = self.Array1[1] // Array1の要素1(dateArray1の保存したもの)をdateArray1に入れる


と書けばいいです。

まだ理解していないみたいですね。
SaveViewController.swiftのviewDidLoad()もおかしいです。
この追記のコードを見て、順番・入る中身をよく考えて、またやってみてください。
func内では基本上から下に順に処理されるんですよ。

理解できれば、なぜprint(resultArray2)とprint(dateArray2)が空なのかわかると思います。

また、エラーは理由が書いてある「Index out of range」ので、
google翻訳でも駆使して、日本語に訳して考えてください。
解決には、以前も書きましたが、

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return Array2.count
}


で返ってくる個数を考えて、何がおかしいのかを考えてください。
わからなければ、print(Array2.count)で個数の確認もできます。

cellforRowatの取り出し方も、データの構造、
順番・取り出し方等を考えればわかるはずです。

そろそろ同じことを何度もやり取りするのは疲れてきました。
答えは全て、このページに載っています。
よく全体を読んで、理解してください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/07 13:52 編集

    //追記1月8日

    追記ありがとうございます!
    ②はコードでいうとどのようになりますか。何度も申し訳ございません。


    ②なしでもアドバイス通りこのような順番でやってみると、Array1にresultArray1とdateArray1の値を入れることができました

    しかし取り出してArray2に入れてみて中身を確認するとArray2には何も入っていません。

    コードは再度追記しましたのでご覧いただけたら幸いです。(1/9)

    キャンセル

0

エラーコードに書かれているとおり、プロパティイニシャライザーの中でresultArray1やresultArray2を使うことができません。

var Array1 = [resultArray1,dateArray1]を
var Array1: [[String]]に変更して、
viewWillAppear()関数の中でArray1 = [resultArray1, dateArray1]を使用してみてはいかがでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/07 14:20

    なぜviewWillAppear?

    キャンセル

  • 2019/01/07 14:55

    SaveViewController.swiftにviewWillAppear()があったのでviewWillAppear()と書いてしまいましたが、viewDidLoad()の方が適切ですね。

    キャンセル

  • 2019/01/07 17:44

    ありがとうございます!エラーは出なくなりましたが、実行ボタンを押したときにcellForRowAtのcell.textLabel!.text = resultArray2[indexPath.row]のところにThread 1: Fatal error: Index out of rangeと出ました。範囲外のindexと言う意味ですが、どこが範囲外なのしょうか。

    キャンセル

  • 2019/01/07 17:52

    cellForRowAtの中身として記載しているArrayと
    numberOfRowsInSectionのArrayの個数をよく考えてみてください。
    わからないなら、printでviewdidload内に記載し、個数を取得してみてください。

    キャンセル

  • 2019/01/08 04:49

    追記に今の状況を記しました。よろしくお願いします。自分でも模索中です。

    キャンセル

  • 2019/01/08 08:08 編集

    なんか色々変ですよ。

    var resultArray2 = [String]()
    var dateArray2 = [String]()
    の後に変更を加えなければ、
    空の配列のままとなり、0を表示します。
    print結果からは何も入ってないってことですね。

    となると、Array2に入っているものが何かが気になりますよね。
    空の配列を保存している懸念があります。
    print("Array2:", Array2.description)を記入して、
    中身を確認しましょう。

    ①UserDefaults.standard.から読み出していますが、
    UserDefaultsには何か保存したのでしょうか???

    ②Array2は resultArray2とdateArray2を持っているので、
    複雑にしたくなければ、それぞれresultArray2とdateArray2別々に
    userdefaultsに保存し、読み出せばいいのではないでしょうか?
    大したメモリの違いにはならなそうですが。
    でも個数の違いに繋がりやすくなってしまうか。。。

    ③そして、viewWillAppearのコードは
    viewDidLoadに入れるべきです。
    tableView.reloadData()のみ残せばいいです。

    ④tableViewのエラーの方も解決していないですよね。
    設定行数(numberofRowsInSection)はArray2.count なので
    print結果から 2個と、

    各行の表示内容(cellForRowAt indexPath)での
    resultArray2[indexPath.row] の個数が一致しないと
    データを全部表示できないですよ。
    (最悪、設定行数が小さくてもいいけど、、、
    逆の設定行数が多く、配列以上の要素の読み出しはエラーになります。)

    まずは、配列をuserdefaultsからではないく、
    見える短いものを用意して作ってみてはどうでしょうか???

    ex)
    resultArray = ["晴れ", "雨", "雪"]
    dateArray = ["2019/1/1", "2019/1/2", "2019/1/3"]
    のように。となると
    Array2 = [ ["晴れ", "雨", "雪"],
    ["2019/1/1", "2019/1/2", "2019/1/3"] ]

    それで何をしたいか、きちんと表示できるか、やってみたらいいと思います。
    その後に置き換えればいいんです。

    キャンセル

  • 2019/01/08 12:17

    print("Array2:", Array2.description)にはArray2: [[], []]が出力されました。

    //Array2にresultArray2とdateArray2を代入
    Array2 = [resultArray2,dateArray2]
    しているからだと思います。

    4,についてですがex)の通りやってみたところ
    晴れ            2019/1/1
    雨             2019/1/2 

    がテーブルビューに出力されました

    そもそもresultViewControllerでUserDefaultsに保存していたArray1にはresultArray1とdateArray1が入っていて、resultArray1には回数(前のViewControllerから受け取った)、dateArray1には日付が入っていたはずで、それをArray2に入れて使おうと思っていたのですが私のやり方がそもそも間違っていたと言うことですよね。

    キャンセル

  • 2019/01/08 13:02 編集

    Array2が空の配列を保存しているという時点で、
    そもそものデータの登録がきちんとできていないですね。

    Userdefaultsに登録するところを見直してみる必要がありそうです。

    キャンセル

  • 2019/01/08 16:01

    print()で確認したところresultArray1とdateArray1には値が入っていましたがArray1には何も入っていませんでした。その何も入っていないArray1を保存していたのでエラーが発生していたものと思われます。viewdidloadで

    Array1 = [resultArray1, dateArray1]

    をしたはずなのに、何も入っていないのはおかしいですね。色々試してみます。

    キャンセル

  • 2019/01/08 18:31

    コードが含まれるので、回答を編集しました。
    見てみてください。

    これで改善すると思います。

    キャンセル

同じタグがついた質問を見る

  • Swift

    8908questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    5019questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。