前提・実現したいこと
設定画面からアラートをクリックしてユーザーデフォルトに値を保存しつつカスタムセルのViewの色を変更したい。
発生している問題・エラーメッセージ
UIView Unexpectedly found nil while implicitly unwrapping an Optional value
カスタムセルのソースコード(必要部分抜粋)
SWIFT
1import UIKit 2 3class StickyCell: UITableViewCell { 4 5 @IBOutlet weak var stickyBubble: UIView! 6 @IBOutlet weak var label: UILabel! 7 8 let defaults = UserDefaults.standard 9 10 override func awakeFromNib() { 11 super.awakeFromNib() 12 13 let cellColor = defaults.color(forKey: "CellColor") 14 15 if (cellColor != nil){ 16 stickyBubble.backgroundColor = cellColor 17 } 18 } 19}
メイン画面のソースコード
SWIFT
1import UIKit 2import CoreData 3import GrowingTextView 4 5class ViewController: UIViewController,UITableViewDelegate,UIGestureRecognizerDelegate { 6 7 @IBOutlet weak var inputToolbar: UIView! 8 @IBOutlet weak var tableView: UITableView! 9 @IBOutlet weak var textView: GrowingTextView! 10 @IBOutlet weak var textViewBottomConstraint: NSLayoutConstraint! 11 12 var itemArray = [Item]() 13 let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 14 15 let defaults = UserDefaults.standard 16 17 override func viewDidLoad() { 18 super.viewDidLoad() 19 20 // *** Customize GrowingTextView *** 21 textView.layer.cornerRadius = 4.0 22 tableView.contentInset = UIEdgeInsets(top: 15,left: 0,bottom: 15,right: 0) 23 24 print(FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)) 25 26 textView.delegate = self 27 tableView.dataSource = self 28 tableView.delegate = self 29 30 tableView.register(UINib(nibName: "StickyCell", bundle: nil), forCellReuseIdentifier: "ReusableCell") 31 32 loadItems() 33 34 // ロングプレス 35 let longPressGesture = 36 UILongPressGestureRecognizer(target: self, 37 action: #selector(ViewController.longPress(_:))) 38 39 longPressGesture.delegate = self 40 self.view.addGestureRecognizer(longPressGesture) 41 } 42 43 override func viewWillAppear(_ animated: Bool) { 44 super.viewWillAppear(animated) 45 46 47 } 48 49 // Long Press イベント 50 @objc func longPress(_ sender: UILongPressGestureRecognizer){ 51 let point = sender.location(in: tableView) 52 let indexPath = tableView.indexPathForRow(at: point) 53 if sender.state == .began { 54 let alert: UIAlertController = UIAlertController(title: "メッセージの削除", message: "削除してもいいですか?", preferredStyle: UIAlertController.Style.alert) 55 56 let defaultAction: UIAlertAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler:{ 57 (action: UIAlertAction!) -> Void in 58 print(indexPath!.row) 59 self.context.delete(self.itemArray[indexPath!.row]) 60 self.itemArray.remove(at: indexPath!.row) 61 62 self.saveItems() 63 }) 64 65 let cancelAction: UIAlertAction = UIAlertAction(title: "キャンセル", style: UIAlertAction.Style.cancel, handler:{ 66 (action: UIAlertAction!) -> Void in 67 print("Cancel") 68 }) 69 70 alert.addAction(cancelAction) 71 alert.addAction(defaultAction) 72 73 present(alert, animated: true, completion: nil) 74 } 75 } 76 77 @IBAction func addButton(_ sender: UIButton) { 78 loadMessages() 79 } 80 81 func textFieldShouldReturn(_ textView: UITextField) -> Bool { 82 loadMessages() 83 84 return false 85 } 86 87 88 func loadMessages() { 89 if textView.text == "" { 90 print("error") 91 } else { 92 93 let newItem = Item(context: context) 94 newItem.text = textView.text! 95 96 itemArray.append(newItem) 97 98 textView.resignFirstResponder() 99 100 saveItems() 101 } 102 DispatchQueue.main.async { 103 self.textView.text = "" 104 let indexPath = IndexPath(row: self.itemArray.count - 1, section: 0) 105 self.tableView.scrollToRow(at: indexPath, at: .top, animated: true) 106 } 107 } 108 109 func saveItems() { 110 111 do{ 112 try context.save() 113 } catch { 114 print("Error saving context (error)") 115 } 116 117 tableView.reloadData() 118 119 } 120 121 func loadItems() { 122 let request : NSFetchRequest<Item> = Item.fetchRequest() 123 do { 124 itemArray = try context.fetch(request) 125 } catch { 126 print("Error fetching data from context (error)") 127 } 128 } 129 130 @IBAction func settingButtonAction(_ sender: UIBarButtonItem) { 131 performSegue(withIdentifier: "goSetting", sender: nil) 132 } 133 134 func cellUpdate(){ 135 136 itemArray.removeAll() 137 print("remove") 138 139 loadItems() 140 141 DispatchQueue.main.async { 142 self.tableView.reloadData() 143 } 144 145 } 146 147} 148 149extension ViewController: UITableViewDataSource{ 150 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 151 return itemArray.count 152 } 153 154 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 155 let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! StickyCell 156 cell.label.text = itemArray[indexPath.row].text 157 return cell 158 } 159} 160 161extension UserDefaults { 162 163 func color(forKey key: String) -> UIColor? { 164 165 guard let colorData = data(forKey: key) else { return nil } 166 167 do { 168 return try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: colorData) 169 } catch let error { 170 print("color error (error.localizedDescription)") 171 return nil 172 } 173 174 } 175 176 func set(_ value: UIColor?, forKey key: String) { 177 178 guard let color = value else { return } 179 do { 180 let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: false) 181 set(data, forKey: key) 182 } catch let error { 183 print("error color key data not saved (error.localizedDescription)") 184 } 185 186 } 187 188} 189 190extension ViewController: GrowingTextViewDelegate { 191 192 // *** Call layoutIfNeeded on superview for animation when changing height *** 193 194 func textViewDidChangeHeight(_ textView: GrowingTextView, height: CGFloat) { 195 UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.7, options: [.curveLinear], animations: { () -> Void in 196 self.view.layoutIfNeeded() 197 }, completion: nil) 198 } 199} 200
設定画面のソースコード(必要部分抜粋)
SWIFT
1import UIKit 2 3class SettingTableViewController: UITableViewController { 4 5 let defaults = UserDefaults.standard 6 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 } 10 11 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 12 let alert: UIAlertController = UIAlertController(title: "セルカラー", message: "", preferredStyle: UIAlertController.Style.alert) 13 14 let defaultAction_1: UIAlertAction = UIAlertAction(title: "標準", style: UIAlertAction.Style.default, handler:{ 15 (action: UIAlertAction!) -> Void in 16 self.defaults.set(originalGreen, forKey: "CellColor") 17 let cellColor = self.defaults.color(forKey: "CellColor") 18 19 let stickyCell = StickyCell() 20 stickyCell.stickyBubble.backgroundColor = cellColor 21 22 }) 23 24 alert.addAction(defaultAction_1) 25 26 present(alert, animated: true, completion: nil) 27 } 28}
問題となっているコード
SWIFT
1let stickyCell = StickyCell() 2stickyCell.stickyBubble.backgroundColor = cellColor
試したこと(設定画面アラートクリックアクション)
アラートクリックで色を変更しようとしましたが上記のエラーでクラッシュしてしまいます。
カスタムセル上でstickyCell.stickyBubble.backgroundColorをプリントした際はnilではない。
アプリを再起動した際にはセルの色が変更されているのでユーザーデフォルトへの保存までは成功しております。
ユーザーデファルトに値は保存されているのでメインの画面に戻りセルをリロードして色を変更しようと試しましたが新しいセルを追加した際は色が変更されるが既存のセルは色が変更されておらずうまくいきませんでした。
補足情報
SWIFT初心者でいたらないこともあると思いますが何卒よろしくお願い申し上げます。
実現したいイメージ
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/09/03 07:11
2020/09/03 07:36
2020/09/03 07:49
2020/09/03 09:16
2020/09/03 12:24