如何解决将通过 WatchConnectivity 接收到的 UserInfo 保存到 CoreData
嗨,我想知道是否有人可以提供帮助。我有手表应用程序进行检查,然后将两位数据传递给主应用程序(一个字符串和一个 Int)。然后我希望它将它们保存到 CoreData。我已经尝试了几件事。注释掉代码是我需要将它们保存到 CoreData。
#if os(iOS)
// With This get *SwiftUI:0: Fatal error: No ObservableObject of type DataController found. A View.environmentObject(_:) for DataController may be missing as an ancestor of this view.*
@EnvironmentObject var dataController: DataController
// This does saved to CoreData but then crashes the iOS app!
// @ObservedObject var dataController = DataController()
func session(_ session: WCSession,didReceiveUserInfo userInfo: [String : Any] = [:]) {
DispatchQueue.main.async {
print("Data received \(userInfo)")
// let viewContext = dataController.container.viewContext
if let isDefect = userInfo["isDefect"] as? Bool {
if isDefect {
// This is another data that save to different entity
print("Defect")
// let defect = Defect(context: viewContext)
} else {
print("Vehicle check")
// let checkData = CheckData(context: viewContext)
//
if let bonnet = userInfo["bonnet"] as? String {
// checkData.bonnet = bonnet
print(bonnet)
}
//
if let numberDefect = userInfo["numberDefect"] as? Int {
// checkData.numberDefect = Int64(numberDefect)
print("\(numberDefect)")
}
//
// checkData.dateCreated = Date()
}
}
// dataController.save()
}
}
// other Protocol methods that are required
#else
// watch Protocol method
#endif
解决方法
如果您将所有这些都提供给您的 iOS 和 WatchKit 扩展,您将拥有一个工作示例
import SwiftUI
struct WatchConnectView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \CheckData.dateCreated,ascending: true)],animation: .default) private var items: FetchedResults<CheckData>
let wcManager = WatchConnectivityManager.shared
var body: some View {
VStack{
Button("send vehicle check",action: {
wcManager.sendVehicleCheck()
})
List {
ForEach(items) { item in
Text("CheckData at \(item)")
}
}
}
}
}
struct WatchConnectView_Previews: PreviewProvider {
static var previews: some View {
WatchConnectView()
}
}
//This would handle all the work for watch connectivity regardless of target
import WatchConnectivity
class WatchConnectivityManager: NSObject,Identifiable {
let id = UUID()
private let session: WCSession = .default
var isReachable: Bool{
session.isReachable
}
//Need singleton because of delegate
static let shared: WatchConnectivityManager = WatchConnectivityManager()
//If you have target specific code it is easier to manage if it is separated
let targetSpecifc = WatchConnectivityManagerTS()
private override init() {
super.init()
session.delegate = self
session.activate()
}
func sendUserInfo(userInfo: [String: Any]){
if isReachable{
session.transferUserInfo(userInfo)
}
}
func sendVehicleCheck(bonnet: String = "Some Bonnet",numberDefect: Int = Int.random(in: 0...50)){
var userInfo: [String: Any] = [:]
userInfo["isDefect"] = false
userInfo["bonnet"] = bonnet
userInfo["numberDefect"] = numberDefect
sendUserInfo(userInfo: userInfo)
}
}
extension WatchConnectivityManager: WCSessionDelegate{
#if os(iOS)
func sessionDidBecomeInactive(_ session: WCSession) {
}
func sessionDidDeactivate(_ session: WCSession) {
}
#endif
func session(_ session: WCSession,activationDidCompleteWith activationState: WCSessionActivationState,error: Error?) {
if let error = error{
print(error)
}
}
func session(_ session: WCSession,didReceiveUserInfo userInfo: [String : Any] = [:]) {
if let isDefect = userInfo["isDefect"] as? Bool {
if isDefect {
print("Defect")
} else {
print("Vehicle check")
targetSpecifc.saveVehicleCheck(userInfo: userInfo)
}
}
}
func session(_ session: WCSession,didReceiveMessage message: [String : Any],replyHandler: @escaping ([String : Any]) -> Void) {
}
func session(_ session: WCSession,didReceiveMessage message: [String : Any]) {
}
}
//Asuming CoreData is only on iOS
#if !os(watchOS)
class DataController{
//Access to the context depends on how you are creating the stack.
//This is with the standard PersistenceController setup that
//comes with XCode sample code
let context = PersistenceController.shared.container.viewContext
init(){}
func newCheckData() -> CheckData{
let new = CheckData(context: context)
new.dateCreated = Date()
return new
}
func saveContext(){
do{
try context.save()
}catch{
print(error)
}
}
}
class WatchConnectivityManagerTS{
let dataController = DataController()
func saveVehicleCheck(userInfo: [String: Any]){
let checkData = self.dataController.newCheckData()
if let bonnet = userInfo["bonnet"] as? String {
checkData.bonnet = bonnet
print(bonnet)
}
if let numberDefect = userInfo["numberDefect"] as? Int {
checkData.numberDefect = Int64(numberDefect)
print("\(numberDefect)")
}
dataController.saveContext()
}
}
#else
class WatchConnectivityManagerTS{
//In case there is a reason for the watch to receive vechicle checks
func saveVehicleCheck(userInfo: [String: Any]){
print("save attempt on watch \(userInfo)")
}
}
#endif
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。