前提・実現したいこと
ToDoリストのようなアプリで、追加したセルのボタンを押すとタイマーが作動して勉強時間を計測したい。
発生している問題・エラーメッセージ
バックグラウンドでタイマーが停止してしまうことと、一度アプリを閉じてタイマーの開始ボタンを押下すると、
Can't end BackgroundTask: no background task exists with identifier 6 (0x6), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
というメッセージが表示され、タイマーが動かなくなる(セルの追加や削除は行えます)
該当のソースコード
Swift
1class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIApplicationDelegate { 2 3 @IBOutlet weak var regiButton: UIButton! 4 @IBOutlet weak var textInput: UITextField! 5 var item:Item? 6 var items = [Item]() 7 let userDefaults = UserDefaults.standard 8 var timer: Timer? 9 var count: Int = 0 10 11 12 func encodeData() { 13 let encodedData = try! NSKeyedArchiver.archivedData(withRootObject: items, requiringSecureCoding: false) 14 userDefaults.set(encodedData, forKey: "items") 15 userDefaults.synchronize() 16 } 17 18 func decodeData() { 19 if let storedData = userDefaults.data(forKey: "items") { 20 let decodedData = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(storedData) as? [Item] 21 items = decodedData! 22 tableView.reloadData() 23 } 24 } 25 26 //カテゴリー登録 27 @IBAction func regiButtonOnPressed(_ sender: Any) { 28 //テキスト取得 29 let text = textInput.text 30 if text != "" { 31 //インスタンス生成 32 let item = Item(name: text!, time: "0") 33 //配列に追加 34 items.append(item) 35 //Data型に変換して保存 36 encodeData() 37 decodeData() 38 } 39 textInput.text = "" 40 } 41 42 // 43 // 44 //タイマー 45 @IBAction func startButtonOnPressed(_ sender: UIButton) { 46 if sender.self.currentTitle == "START" { 47 sender.self.setTitle("STOP", for: .normal) 48 //タイマースタート 49 timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateCount), userInfo: nil, repeats: true) 50 } else { 51 sender.self.setTitle("START", for: .normal) 52 //タイマーストップ 53 timer?.invalidate() 54 //親のcontentviewを取得 55 if let parentContentView = sender.self.superview { 56 //contentviewの親のcellを取得 57 if let parentCell = parentContentView.superview as? UITableViewCell { 58 //取得したcellのindexを取得 59 let row = tableView.indexPath(for: parentCell)?.row 60 let stopTime = count 61 var storedTime = Int(items[row!].time) 62 storedTime = storedTime! + stopTime 63 items[row!].time = String(storedTime!) 64 print(items[row!].time + "です") 65 } 66 } 67 count = 0 68 } 69 } 70 71 @objc func updateCount() { 72 count = count + 1 73 print(count) 74 } 75 76 77 func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { 78 return true 79 } 80 81 //セル数指定 82 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 83 return items.count 84 } 85 86 //セルの生成 87 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 88 let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) 89 cell.textLabel!.text = items[indexPath.row].name 90 return cell 91 } 92 93 //セル削除時の処理 94 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { 95 if editingStyle == UITableViewCell.EditingStyle.delete { 96 items.remove(at: indexPath.row) 97 tableView.deleteRows(at: [indexPath as IndexPath], with: UITableView.RowAnimation.automatic) 98 encodeData() 99 decodeData() 100 } 101 } 102 103 104 @IBOutlet weak var tableView: UITableView! 105 override func viewDidLoad() { 106 super.viewDidLoad() 107 108 if let defaultData = userDefaults.data(forKey: "items") { 109 //デコードする 110 let decodedData = try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(defaultData) as? [Item] 111 items = decodedData! 112 } 113 } 114} 115
//自作クラスの定義(別ファイルで管理) class Item: NSObject, NSCoding, NSSecureCoding { static var supportsSecureCoding = true var name:String var time:String init(name:String, time:String) { self.name = name self.time = time } func encode(with coder: NSCoder) { coder.encode(name, forKey: "name") coder.encode(time, forKey: "time") } required init?(coder: NSCoder) { name = coder.decodeObject(forKey: "name") as! String time = coder.decodeObject(forKey: "time") as! String } }
どこのソースコードが影響しているのか判断がつかなかったため、全文を掲載させていただきます。
試したこと
同じエラー文でググったところ、
こちらが見つかったため、
Symbolic BreakpointにUIApplicationEndBackgroundTaskErrorと入力、同じようにアプリを再起動させたところ
UIKitCore`UIApplicationEndBackgroundTaskError: -> 0x109976334 <+0>: pushq %rbp 0x109976335 <+1>: movq %rsp, %rbp 0x109976338 <+4>: movq %rdi, %rdx 0x10997633b <+7>: leaq 0x96e01e(%rip), %rdi ; @"Can't end BackgroundTask: no background task exists with identifier %lu (0x%lx), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug." 0x109976342 <+14>: movq %rdx, %rsi 0x109976345 <+17>: xorl %eax, %eax 0x109976347 <+19>: callq 0x109ee9988 ; symbol stub for: NSLog 0x10997634c <+24>: popq %rbp 0x10997634d <+25>: retq
が表示され、
-> 0x109976334 <+0>: pushq %rbp
に対して「Thread 1: breakpoint 1.」が表示され、これについても調べたのですが有効な手段が分かりませんでした。
補足情報(FW/ツールのバージョンなど)
swift 5.1.3
Xcode 11.3
シミュレーター iPhone Xs iOS 13.3
回答1件
あなたの回答
tips
プレビュー