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

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

ただいまの
回答率

87.48%

[Swift]TableViewCellに配列(構造体)のデータが表示されない

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,784

score 37

ご覧いただき、有難うございます。
現在スケジュールアプリを作成しております。
ユーザーが指定した「開始時刻(startDate)」「終了時刻(endDate)」「タイトル(title)」を構造体にまとめ、配列として表示したいと思っています。
また、並び順は開始時刻の昇順で表示したいと思っています。

「開始時刻(startDate)」「終了時刻(endDate)」「タイトル(title)」は、DetailsViewController.swiftにてテキストフィールドに入力された値をschedules(構造体ScheduleDataのインスタンス)に追加します。その後、schedulesをNSDictionaryに変換しUserDefaultsに保存しています。
ViewController.swiftのTableViewCellにはtimeLabel(開始時刻+終了時刻を表示するラベル(UILabel))とtitleLabel(タイトルを表示するラベル(UILabel))を置いています。各ラベルはTableViewCell.swiftという別ファイルに接続して、ViewControllerで呼び出しています。
各ラベルにUserDefaultsにて保存したschedulesから取り出した「開始時刻(Date)」「終了時刻(Date)」「タイトル(String)」を表示したいと思っています。

上記を踏まえてコードを書いたのですが、セルに何も表示されません。
以下に関係性があるであろうコードを記述致します。
その他に確認が必要な箇所のコードが有りましたら、ご指摘くださいませ。
また、質問内容でわかりにくい点がありましたら、そちらもご指摘くださいませ。

//  SchedulesData.swift

import Foundation

/* 表示データ */
struct ScheduleData{
  // スケジュールのコメント
  var title: String = ""
  // スケジュールの開始時間
  var startDate: Date!
  // スケジュールの終了時間
  var endDate: Date!

  init(title : String , startDate : Date , endDate : Date){
    self.title = title
    self.startDate = startDate
    self.endDate = endDate
  }
}


extension UserDefaults {
  var logDataArray:[ScheduleData]{
    set(datas){
      // Swiftのオブジェクトを、NSObjectなオブジェクトに変換する
      let newDatas:[NSDictionary] = datas.map{
        ["title":$0.title,
         "startdate":$0.startDate,
         "endDate":$0.endDate] as NSDictionary
      }
      // NSObjectなオブジェクトのみになったから、setObjectできる
      self.set(newDatas,forKey:"schedules")
    }
    get{
      // NSDictionaryの配列として、データを取得
      let datas = self.object(forKey: "schedules") as? [NSDictionary] ?? []
      // 保存されたデータから復元出来無い場合もあり得るので、
      // mapではなくreduceを使う
      let array = datas.reduce([]){ (ary, d:NSDictionary) -> [ScheduleData] in
        // dateやmessageがnilでないなら、MyLogDataを作って足し込む
        if let title = d["title"] as? String,
          let endDate = d["endDate"] as? Date,
          let startDate = d["startDate"] as? Date {
          return ary + [ScheduleData(title: title, startDate: startDate, endDate: endDate)]
        }else{
          return ary
        }
      }
      return array
    }
  }
}
//  DetailsViewController.swift

  func saveData() {

      dataOut()

    if dateTextField.text! != nil {

      if dateTextField2.text! != nil {

        if titleTextField.text! != nil {

          dateFromString = myDateFormatter.date(from: dateTextField.text!)!
          dateFromString2 = myDateFormatter.date(from: dateTextField2.text!)!
          dateArrayFromString.append(dateFromString)
          dateArrayFromString.append(dateFromString2)


          schedules.append(ScheduleData(title:titleTextField.text!, startDate: dateFromString, endDate: dateFromString2))
          detailArray.append(detailTextView.text!)
          placeArray.append(placeTextField.text!)
          urlArray.append(urlTextField.text!)
          alarmDateArray.append(alarmTimeTextField.text!)

          UserDefaults.standard.logDataArray = schedules

          UserDefaults.standard.set(detailArray, forKey: "detailArray")
          UserDefaults.standard.set(placeArray, forKey: "placeArray")
          UserDefaults.standard.set(urlArray, forKey: "urlArray")
          UserDefaults.standard.set(alarmDateArray, forKey: "alarmDateArray")

        }

      }

    } else {

      warningAlertController()

      }

  }
//  ViewController.swift
  func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {



    return false
  }

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


    return schedules.count

  }


  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableViewCell

    func dateString(date: NSDate) -> String {
      let dateFormatter = DateFormatter()
      dateFormatter.calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)! as Calendar!
      dateFormatter.locale = NSLocale.system
      dateFormatter.timeZone = NSTimeZone.system
      dateFormatter.dateFormat = "H:mm"
      let dateString: String = dateFormatter.string(from: date as Date)
      return dateString
    }


    strBox.append(dateString(date: sortedSchedules[indexPath.row].startDate as NSDate))
    strBox2.append(dateString(date: sortedSchedules[indexPath.row].endDate as NSDate))
    dateInStr = dateString(date: sortedSchedules[indexPath.row].startDate as NSDate)
    dateInStr2 = dateString(date: sortedSchedules[indexPath.row].endDate as NSDate)

    strCount = dateInStr.characters.count
    strCount2 = dateInStr2.characters.count

    if strCount < 5 {

      timeLabelText1 = " " + strBox[indexPath.row]! + "  "

    } else {

      timeLabelText1 = strBox[indexPath.row]! + "  "

    }

    if strCount2 < 5 {

      timeLabelText2 = "   " + strBox2[indexPath.row]!

    } else {

      timeLabelText2 = "  " + strBox2[indexPath.row]!

    }

    let attrText = NSMutableAttributedString(string: timeLabelText1 + ">>>" + timeLabelText2)
    attrText.addAttribute(NSForegroundColorAttributeName,
                          value: UIColor.red,
                          range: NSMakeRange(7, 3))

    attrText.addAttribute(NSForegroundColorAttributeName,
                          value: UIColor.white,
                          range: NSMakeRange(0, 5))
    attrText.addAttribute(NSForegroundColorAttributeName,
                          value: UIColor.white,
                          range: NSMakeRange(12, 5))

    cell.timeLabel?.attributedText = attrText

    cell.titleLabel?.text = "   " + sortedSchedules[indexPath.row].title

    // 枠のカラー
    cell.titleLabel.layer.borderColor = UIColor.darkGray.cgColor

    // 枠の幅
    cell.titleLabel.layer.borderWidth = 1.0

    // 枠を角丸にする
    cell.titleLabel.layer.cornerRadius = 10.0
    cell.titleLabel.layer.masksToBounds = true

    return cell

  }
//ViewWillApperに呼び出しています。
  func dataOut() {



    if UserDefaults.standard.logDataArray != nil {
      schedules = UserDefaults.standard.logDataArray
    }

    if UserDefaults.standard.array(forKey: "detailArray") != nil {

      detailArray = UserDefaults.standard.array(forKey: "detailArray") as! [String]

    }
    if UserDefaults.standard.array(forKey: "placeArray") != nil {

      placeArray = UserDefaults.standard.array(forKey: "placeArray") as! [String]

    }
    if UserDefaults.standard.array(forKey: "urlArray") != nil {

      urlArray = UserDefaults.standard.array(forKey: "urlArray") as! [String]

    }
    if UserDefaults.standard.array(forKey: "alarmDateArray") != nil {

      alarmDateArray = UserDefaults.standard.array(forKey: "alarmDateArray") as! [String]

    }


  }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • fuzzball

    2017/05/26 11:46 編集

    「セルに何も表示されません」ということは、セル自体は表示されているということでしょうか?

    キャンセル

  • niship

    2017/05/26 11:57

    今確認してみると、セルが表示されていませんでした。 一旦、CellForRowAt内の 記述をlet cell = と return cell 以外、削除し numberOfRowsInectionの戻り値をreturn 1 変えて検証してみるとセルが表示されました。

    キャンセル

  • fuzzball

    2017/05/26 12:50 編集

    tableView(_:numberOfRowsInSection:)の中に print(schedules.count) を追加してschedulesの中身があるかどうか確認して下さい。

    キャンセル

  • niship

    2017/05/26 12:54

    print(schedules.count)を記述すると、デバックエリアに 0 0 0 0 と表示されました。

    キャンセル

回答 1

0

dataOut()をviewDidLoad()で呼び出して下さい。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/05/26 13:23

    確認したところ、
    []
    0
    0
    0
    0
    と表示されました。

    キャンセル

  • 2017/05/26 13:31 編集

    前の質問で、schedulesを保存/取得出来ているなら別の質問にして下さいと書きましたが、取得できてないですよね?

    キャンセル

  • 2017/05/26 13:37

    前の質問ではコンパイルエラーが消え、シミュレータでクラッシュすることもなくなったので、schedulesは保存できているけど、何らかの理由で表示されていないと勘違いしておりました。申し訳有りません。

    キャンセル

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

  • ただいまの回答率 87.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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