前提
プログラミング初心者、そして初めての質問ですので、至らない点多々あると思いますが、xcode,アプリ作成に詳しい方、回答していただけたら幸いです。
SwiftUIでWatch 側のアニマルリストをタップすると選択されたアニマルの絵文字とテキストおよびタップ時の時刻をiPhone 側にバックグラウンドで送信し,iPhone のアプリ起動時に受信して画面更新するアプリを作ることを目標にしています。
使用開発ソフトはXcodeでiosAppWithWatchAppを選択しました。開発モジュールはstoryboardではなくswiftUIです。
参考にしたサイトは以下になっており、コードをコピペさせていただきました。
https://qiita.com/MilanistaDev/items/0ce079b255034be84472
成功例をコピぺしたにもかかわらず、うまく機能しなかったので、なぜエラーが発生してしまっているのか教えていただけると嬉しいです。
実現したいこと
ここに実現したいことを箇条書きで書いてください。
- ▲▲機能を動作するようにする
発生している問題・エラーメッセージ
エラーメッセージ(私の知識が乏しく、どのコードを載せれば解決につながるのか予想がつかなかったため、一応全てのファイルのコードを記します。) エラーは発生行付近にコメントアウトして記してあります。 iPhone側のファイル ・AnimalListApp(エラーなし) import SwiftUI @main struct AnimalListApp: App { var body: some Scene { WindowGroup { ReceiverView() } } } ・ContentView import SwiftUI struct ReceiverView: View { @StateObject var viewModel = ReceiverViewModel() var body: some View { List { //エラー① Generic parameter 'Content' could not be inferred,②Explicitly specify the generic arguments to fix this issue ForEach(viewModel.records, id: \.self) { record in VStack(alignment: .leading) { Text(record.animal.emoji + record.animal.name) .font(.body) .padding(.vertical, 4.0) Text(record.timeStamp.toString()) .font(.footnote) .foregroundColor(.gray) } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ReceiverView() } } ・ReceiverViewModel(追加ファイル) import WatchConnectivity final class ReceiverViewModel: NSObject, ObservableObject { @Published var records: [Record] = [] private let session: WCSession init(session: WCSession = .default) { self.session = session super.init() self.session.delegate = self session.activate() } } extension ReceiverViewModel: WCSessionDelegate { func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { if let error = error { print(error.localizedDescription) } else { print("The session has completed activation.") } } func sessionDidBecomeInactive(_ session: WCSession) { } func sessionDidDeactivate(_ session: WCSession) { } func session(_ session: WCSession, didRecieveUserInfo userInfo: [String : Any] = [:]) { guard let data = userInfo["record"] as? Data, let record = try? JSONDecoder().decode(Record.self, from: data) else { // エラー③ Cannot find 'Record' in scope return } self.records.append(record) } } applewatch側のファイル ・AnimalListApp(エラーなし) import SwiftUI @main struct AnimalListApp: App { @SceneBuilder var body: some Scene { WindowGroup { NavigationView { AnimalListView() } } WKNotificationScene(controller: NotificationController.self, category: "myCategory") } } ・ContentView import SwiftUI struct AnimalListView: View { private let viewModel = AnimalListViewModel() var body: some View { List { ForEach(animals, id: \.self) { animal in Button { // Send Animal viewModel.transfer(animal: animal) } label: { HStack(spacing: 16.0) { Text(animal.emoji) .font(.title) Text(animal.name) } .padding(.vertical, 20.0) } } } .listStyle(CarouselListStyle()) } } struct ContentView_Previews: PreviewProvider { static var previews: some View { AnimalListView() } } ・Record(追加ファイル、エラーなし) import Foundation struct Record: Hashable, Codable { var animal: Animal var timeStamp: Date } ・Animal(追加ファイル、エラーなし) import Foundation struct Animal: Hashable, Codable { var name: String var emoji: String } let animals: [Animal] = [ Animal(name: "ネコ", emoji: "🐱"), Animal(name: "イヌ", emoji: "🐶"), Animal(name: "ハムスター", emoji: "🐹"), Animal(name: "ドラゴン", emoji: "🐲"), Animal(name: "ユニコーン", emoji: "🦄"), ] ・AnimalListViewModel(追加ファイル、エラーなし) import WatchConnectivity final class AnimalListViewModel: NSObject { private let session: WCSession init(session: WCSession = .default) { self.session = session super.init() self.session.delegate = self session.activate() } func transfer(animal: Animal) { let record = Record(animal: animal, timeStamp: Date()) guard let data = try? JSONEncoder().encode(record) else { return } let userInfo: [String: Any] = ["record": data] self.session.transferUserInfo(userInfo) } } extension AnimalListViewModel: WCSessionDelegate { func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { if let error = error { print(error.localizedDescription) } else { print("The session has completed activation.") } } } ・NotificationController ・NotificationView ・ComplicationController は変更なしなので記載省かせていただきます。
試したこと
エラーについて検索をかけてみたのですが、該当する情報が見つからず、困っています。
全てのエラーはおそらく変数RecordがiPhone側のアプリに登録されていないことが原因なのですが、applewatch側で用いたRecordをiphone側ファイルでも同様に宣言しなくてはいけないのでしょうか。
試しにAnimal,Recordファイルをiphone側のファイルにコピペしてみましたが、次は別のエラーが発生し、
ContentViewのListの中にある.toString()がDateに対応していないというエラーが出てしまいました。
補足情報(FW/ツールのバージョンなど)
Xcode Version 13.4.1 (13F100)
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/09/16 05:54