◎わからないこと
apple watch で心拍数を図るアプリを作りたいので下記のようにコードを記述しましたが、libc++abi.dylib: terminating with uncaught exception of type NSException
のエラーが出てします。
修正したいがどうすればよいか分からない。
◎試したこと
1,Interface.storyboardで@IBOutletとのリンクを切って再接続したが状況は変わらない。重複もない。
2,ブレークポイントで確認したら下記の箇所が怪しい。
// アクセス許可をユーザに求める
let dataTypes = Set([self.heartRateType])
self.healthStore.requestAuthorization(toShare: nil, read: dataTypes) { (success, error) -> Void in
guard success else {
self.label.setText("not allowed")
return
}
}
◎エラー文
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
◎すべてのコード
import WatchKit
import Foundation
import HealthKit
import WatchConnectivity
class InterfaceController: WKInterfaceController {
// @IBOutlet var label: WKInterfaceLabel!
// @IBOutlet var messageLabel: WKInterfaceLabel!
// @IBOutlet var button: WKInterfaceButton!
// @IBOutlet var secondbutton: WKInterfaceButton!
@IBOutlet weak var label: WKInterfaceLabel!
@IBOutlet weak var messageLabel: WKInterfaceLabel!
@IBOutlet weak var button: WKInterfaceButton!
@IBOutlet weak var secondbutton: WKInterfaceButton!
// HealthKitで扱うデータを管理するクラス(データの読み書きにはユーザの許可が必要)
let healthStore = HKHealthStore()
// 取得したいデータの識別子、今回は心拍数
let heartRateType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
// 取得したデータの単位、今回はBPM
let heartRateUnit = HKUnit(from: "count/min")
// HealthStoreへのクエリ
//HealthKitのすべてのクエリクラスの抽象クラス
var heartRateQuery: HKQuery?
//iphoneと通信
var wcSession = WCSession.default
override func awake(withContext context: Any?) {
super.awake(withContext: context)
// check supported
if WCSession.isSupported() {
// get default session
wcSession = WCSession.default
// set delegate
wcSession.delegate = self as? WCSessionDelegate
// activate session
wcSession.activate()
} else {
print("Not support WCSession")
}
// iPhoneとAppleWatchの連携チェック
if WCSession.isSupported() {
wcSession.delegate = self as? WCSessionDelegate
wcSession.activate()
}
// Configure interface objects here.
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
// HealthKitがデバイス上で利用できるか確認
guard HKHealthStore.isHealthDataAvailable() else {
self.label.setText("not available")
return
}
// アクセス許可をユーザに求める
let dataTypes = Set([self.heartRateType])
self.healthStore.requestAuthorization(toShare: nil, read: dataTypes) { (success, error) -> Void in
guard success else {
self.label.setText("not allowed")
return
}
}
}
// healthStoreへのクエリ生成
private func createStreamingQuery() -> HKQuery {
let predicate = HKQuery.predicateForSamples(withStart: NSDate() as Date, end: nil, options: [])
// HKAnchoredObjectQueryだと他のアプリケーションによる更新を検知
let query = HKAnchoredObjectQuery(type: heartRateType, predicate: predicate, anchor: nil, limit: Int(HKObjectQueryNoLimit)) { (query, samples, deletedObjects, anchor, error) -> Void in
self.addSamples(samples: samples)
}
query.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in
self.addSamples(samples: samples)
}
return query
}
// 取得したデータを表示,保存
private func addSamples(samples: [HKSample]?){
guard let samples = samples as? [HKQuantitySample] else {
return
}
guard let quantity = samples.last?.quantity else {
return
}
let hartrate = (quantity.doubleValue(for: heartRateUnit))
label.setText("\(hartrate)")
print(hartrate)
let file_name = "test_HR.txt"
let text = "\(hartrate)"
let path = NSHomeDirectory() + "/Documents/\(file_name)"
print("\(path)")
do{
try text.write(toFile: path, atomically: true, encoding: String.Encoding.utf8)
print("書き込み成功")
}catch{
print("失敗")
//print(message)
}
}
@IBAction func buttonTapped() {
if self.heartRateQuery == nil {
// start
// クエリ生成
self.heartRateQuery = self.createStreamingQuery()
// クエリ実行
self.healthStore.execute(self.heartRateQuery!)
self.button.setTitle("Stop")
self.messageLabel.setText("Measuring...")
}
else {
// end
self.healthStore.stop(self.heartRateQuery!)
self.heartRateQuery = nil
self.button.setTitle("Start")
self.messageLabel.setText("")
}
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
}
reasonの箇所
2019-09-30 16:54:40.412248+0900 RepMonitor WatchKit Extension[952:12172] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'The string "Save the data" is an invalid value for NSHealthShareUsageDescription'
28 UIKitCore 0x5e24e466 -[UIApplication _stopDeactivatingForReason:] + 1106
32 UIKitCore 0x5da30b37 -[_UISceneLifecycleMultiplexer _performBlock:withApplicationOfDeactivationReasons:fromReasons:] + 468
(lldb)
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
thyda.eiqau
2019/09/30 09:40
エラーの原因を特定するための情報が提示されていないので回答のしようがないです。Exceptionの内容がコンソールに記載されているはずなのでコピペして提示してください。Reasonという単語が出てくる付近です。
あとその画像は先に進みすぎていてどこで止まっているのか分からないので、Breakpointの設定ペインの左下だか右下だかのプラス記号からAll Exceptionに対するBreakpointを追加して、止まったところの画像を提供してください。
AppDvl
2019/09/30 17:14
thyda.eiqauさん
コンソールの全文は文字数の制限で記載できないので「Reason」を検索して、該当箇所を記載しました。
あと『あとその画像は先に進みすぎていてどこで止まっているのか分からないので、Breakpointの設定ペインの左下だか右下だかのプラス記号からAll Exceptionに対するBreakpointを追加して、止まったところの画像を提供してください。』とのことですが、どのボタンのことかわからないので私のxcodeの画面を載せます。赤丸のプラスマークのことでしょうか?
thyda.eiqau
2019/09/30 17:22
> The string "Save the data" is an invalid value for NSHealthShareUsageDescription
とのことなので、 info.plist の NSHealthShareUsageDescription (Privacy - Health Share Usage Description) の値を見直してみてはいかがでしょうか。すべてのロケールで12文字以上である必要があると言っている人もいました (Save the dataは13文字あるような気がしますが……)
あとブレークポイントは位置は合ってるのですが、その画面ではないです。その赤丸からずらーっと上に行くとフォルダーマークがハイライトされていて虫眼鏡とか注意記号とか吹き出しみたいなボタンが並んでいるところがありますよね。その右から2つ目をクリックしてからその辺に出てくるプラスアイコンを押してください。
AppDvl
2019/10/02 20:27
thyda.eiqauさん
info.plistを"Save the HealthData"に変えたら上手く行きました。
ブレークポイントを初めて今回つかってまた知識が増えた気がします(結果的に役に立ちませんでしたが)
これからはエラーメッセージを理解するよう努めます。ありがとうございました。
AppDvl
2019/10/02 20:31
thyda.eiqauさん
この欄は”質問への追記、修正依頼”なので評価が出来ないようです。
解答欄に何かコメントいただければ「ベストアンサー」をつけたいと思いますのでよろしくおねがいします。