私は今iphoneアプリの作成の勉強をしています。「本気で始めるiPhoneアプリ作り Xcode 9.x + Swift4.x対応」という書籍にTableviewを用いたTodoリストアプリのサンプルがありました。サンプルでは右上の+ボタンを押すとAlertが現れて、そこに文字列を入力することでToDoを登録するという方式をとっていました。これをアラートではなく、次の画面に遷移して、次の画面のtextFieldに文字を入力して登録ボタンを押すことによってTodoを登録できるようにしたかったのですが、Fatal errorが出てアプリが落ちてしまいました。どうしたらいいですか?
swift
1import UIKit 2 3class NextViewController: UIViewController { 4 5 @IBOutlet weak var textBox: UITextField! 6 override func viewDidLoad() { 7 super.viewDidLoad() 8 9 // Do any additional setup after loading the view. 10 } 11 12 override func didReceiveMemoryWarning() { 13 super.didReceiveMemoryWarning() 14 // Dispose of any resources that can be recreated. 15 } 16 17 @IBAction func tapButton(_ sender: Any) { 18 let myTodo = MyTodo() 19 myTodo.todoTitle = textBox.text! 20 let firstVC = self.storyboard?.instantiateViewController(withIdentifier: "firstView") as! ViewController 21 firstVC.todoList.insert(myTodo, at: 0) 22 // テーブルに行が追加されたことをテーブルに通知 23 firstVC.tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: UITableViewRowAnimation.right) 24 25 } 26}
swift
1import UIKit 2 3class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 4 5 // ToDoを格納した配列 6 var todoList = [MyTodo]() 7 8 @IBOutlet weak var tableView: UITableView! 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 // Do any additional setup after loading the view, typically from a nib. 13 // 保存しているToDoの読み込み処理 14 let userDefaults = UserDefaults.standard 15 if let storedTodoList = userDefaults.object(forKey: "todoList") as? Data { 16 if let unarchiveTodlList = NSKeyedUnarchiver.unarchiveObject(with: storedTodoList) as? [MyTodo] { 17 todoList.append(contentsOf: unarchiveTodlList) 18 } 19 } 20 } 21 22 override func didReceiveMemoryWarning() { 23 super.didReceiveMemoryWarning() 24 // Dispose of any resources that can be recreated. 25 } 26 27 // もともとの+ボタンを押した際の処理 28// @IBAction func tapAddButton(_ sender: Any) { 29// // アラートダイアログを生成 30// let alertController = UIAlertController(title: "TODO追加", message: "TODOを入力してください", preferredStyle: UIAlertControllerStyle.alert) 31// // テキストエリアを追加 32// alertController.addTextField(configurationHandler: nil) 33// 34// // OKボタンがタップされた時の処理 35// let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) { (action: UIAlertAction) in 36// // OKボタンがタップされた時の処理 37// if let textField = alertController.textFields?.first { 38// // ToDoの配列に入力値を挿入。先頭に挿入する 39// let myTodo = MyTodo() 40// myTodo.todoTitle = textField.text! 41// self.todoList.insert(myTodo, at: 0) 42// 43// // テーブルに行が追加されたことをテーブルに通知 44// self.tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: UITableViewRowAnimation.right) 45// 46// // ToDoの保存処理 47// let userDefaults = UserDefaults.standard 48// // Data型にシリアライズする 49// let data = NSKeyedArchiver.archivedData(withRootObject: self.todoList) 50// userDefaults.set(data, forKey: "todoList") 51// userDefaults.synchronize() 52// } 53// } 54// 55// // OKボタンを追加 56// alertController.addAction(okAction) 57// 58// // CANCELボタンがタップされた時の処理 59// let cancelButton = UIAlertAction(title: "CANCEL", style: UIAlertActionStyle.cancel, handler: nil) 60// // CANCELボタンを追加 61// alertController.addAction(cancelButton) 62// 63// // アラートダイアログを表示 64// present(alertController, animated: true, completion: nil) 65// } 66 67 // テーブルの行数を返却する 68 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 69 // ToDoの配列の長さを返却する 70 return todoList.count 71 } 72 73 // テーブルの行ごとのセルを返却する 74 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 75 // Storyboardで指定したtodoCell識別子を利用して再利用可能なセルを取得する 76 let cell = tableView.dequeueReusableCell(withIdentifier: "todoCell", for: indexPath) 77 78 // 行番号に合ったToDoの情報を取得 79 let myTodo = todoList[indexPath.row] 80 // セルのラベルにToDoのタイトルをセット 81 cell.textLabel?.text = myTodo.todoTitle 82 // セルのチェックマーク状態をセット 83 if myTodo.todoDone { 84 // チェックあり 85 cell.accessoryType = UITableViewCellAccessoryType.checkmark 86 } else { 87 // チェックなし 88 cell.accessoryType = UITableViewCellAccessoryType.none 89 } 90 return cell 91 } 92 93 // セルをタップした時の処理 94 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 95 let myTodo = todoList[indexPath.row] 96 if myTodo.todoDone { 97 // 完了済みの場合は未完了に変更 98 myTodo.todoDone = false 99 } else { 100 // 未完の場合は完了済みに変更 101 myTodo.todoDone = true 102 } 103 104 // セルの状態を変更 105 tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.fade) 106 // データ保存。Data型にシリアライズする 107 let data: Data = NSKeyedArchiver.archivedData(withRootObject: todoList) 108 // UserDefautlsに保存 109 let userDefaults = UserDefaults.standard 110 userDefaults.set(data, forKey: "todoList") 111 userDefaults.synchronize() 112 } 113 114 // セルが編集可能であるかどうかを返却する 115 func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { 116 return true 117 } 118 119 // セルを削除した時の処理 120 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { 121 // 削除処理かどうか 122 if editingStyle == UITableViewCellEditingStyle.delete { 123 // ToDoリストから削除 124 todoList.remove(at: indexPath.row) 125 // セルを削除 126 tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.fade) 127 // データ保存。Data型にシリアライズする 128 let data: Data = NSKeyedArchiver.archivedData(withRootObject: todoList) 129 // UserDefautlsに保存 130 let userDefaults = UserDefaults.standard 131 userDefaults.set(data, forKey: "todoList") 132 userDefaults.synchronize() 133 } 134 } 135} 136 137// 独自クラスをシリアライズする際には、NSObjectを継承し 138// NSCodingプロトコルに準拠する必要がある 139class MyTodo: NSObject, NSCoding { 140 // ToDoのタイトル 141 var todoTitle: String? 142 // ToDoを完了したかどうかを表すフラグ 143 var todoDone: Bool = false 144 // コンストラクタ 145 override init() { 146 147 } 148 149 // NSCodingプロトコルに宣言されているデシリアライズ処理。デコード処理とも呼ばれる 150 required init?(coder aDecoder: NSCoder) { 151 todoTitle = aDecoder.decodeObject(forKey: "todoTitle") as? String 152 todoDone = aDecoder.decodeBool(forKey: "todoDone") 153 } 154 155 // NSCodingプロトコルに宣言されているシリアライズ処理。エンコード処理とも呼ばれる 156 func encode(with aCoder: NSCoder) { 157 aCoder.encode(todoTitle, forKey: "todoTitle") 158 aCoder.encode(todoDone, forKey: "todoDone") 159 } 160} 161
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/16 06:21
2018/03/16 07:02 編集
2018/03/16 08:03