Closed andreaxricci closed 3 years ago
@andreaxricci Have you added the AppDelegate
to your App
struct?
import SwiftUI
@main
struct YourApp: App {
// MARK: - Properties
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
// MARK: - View
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
@ArtNikSolo Thanks for the hint. I've just added this, but unfortunately the error persists
//
// KApp.swift
// Shared
//
// Created by Andrea on 20.10.20.
//
import SwiftUI
@main
struct KApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
It's possible that the issue is related to the use of the environment. Since the store is an object, I'd recommend using environment objects rather than environment values to propagate the store though the view hierarchy.
import SwiftUI
@main
struct KApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(appDelegate.synchronizedStoreManager)
}
}
}
Thanks for the feedback @gavirawson-apple!
My understanding is that in order to make OCKSynchronizedStoreManager conform to 'ObservableObject', I have to add the @Published property wrapper to the variable "synchronizedStoreManager", otherwise I'd get the error
Instance method 'environmentObject' requires that 'OCKSynchronizedStoreManager' conform to 'ObservableObject'
I tried to modify the code for ContentView.swift as follows, but without success.
//
// ContentView.swift
// Shared
//
// Created by Andrea on 20.10.20.
//
import SwiftUI
import UIKit
import CareKit
//Adding the store manager into the App Delegate
class AppDelegate: UIResponder, UIApplicationDelegate, ObservableObject {
// Manages synchronization of a CoreData store
@Published var synchronizedStoreManager: OCKSynchronizedStoreManager = {
//let store = OCKStore(name: "SampleAppStore")
let store = OCKStore(name: "SampleAppStore", type: .onDisk)
store.populateSampleData()
let manager = OCKSynchronizedStoreManager(wrapping: store)
return manager
}()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
}
// Extensions for Store Manager
extension EnvironmentValues {
var storeManager: OCKSynchronizedStoreManager {
get { self[StoreManagerKey.self] }
set { self[StoreManagerKey.self] = newValue }
}
}
private struct StoreManagerKey: EnvironmentKey {
typealias Value = OCKSynchronizedStoreManager
// Define the value to be injected into a view's environment if no other value is explicitly set
static var defaultValue: OCKSynchronizedStoreManager {
let appDelegate = UIApplication.shared.delegate as! AppDelegate // <-- ERROR HERE: Thread 1: signal SIGABRT
let manager = appDelegate.synchronizedStoreManager
return manager
}
}
[...] same as above
I'm still getting the compile error
The conformance to ObservableObject
can be defined in an extension:
extension OCKSynchronizedStoreManager: ObservableObject {}
The store manager doesn't have published properties, so it will not trigger SwiftUI view updates. But that will allow you to store the object in a view and pass it through the environment.
thanks. I confirm that solved the compiling error, but unfortunately it didn't fix the initial SIGABRT exception:
Based on the screenshot its looks like the store manager is still setup as an environment value. Try removing lines 35-51 and see if that solves it.
@andreaxricci okay I think I've found a solution. As @gavirawson-apple said, firstly conform OCKSynchronizedStoreManager
to ObservableObject
extension OCKSynchronizedStoreManager: ObservableObject {}
Then in AppDelegate
class make property synchronizedStoreManager
static
static var synchronizedStoreManager: OCKSynchronizedStoreManager = {
//let store = OCKStore(name: "SampleAppStore")
let store = OCKStore(name: "SampleAppStore", type: .onDisk)
store.populateSampleData()
let manager = OCKSynchronizedStoreManager(wrapping: store)
return manager
}()
In main App
struct add synchronizedStoreManager
property as EnvironmentObject
@main
struct KApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
let persistenceController = PersistenceController.shared
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(AppDelegate.synchronizedStoreManager)
}
}
}
And the last change is in MyView
instead of reading storeManager
from environment add it as EnvironmentObject
struct MyView: UIViewControllerRepresentable {
// Reading the store manager from the environment
@EnvironmentObject private var storeManager: OCKSynchronizedStoreManager
func makeUIViewController(context: Context) -> CareViewController {
CareViewController(storeManager: storeManager)
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
Hope it helps!
Many thanks to both of you, @ArtNikSolo and @gavirawson-apple
much appreciated! I confirm the error is solved.
Hi,
I'm trying to replicate the sample App using SwiftUI, but my code is crashing and I can't figure out why. The error I get is "Thread 1: signal SIGABRT" and is linked to the section of ContentView.swift where I define the environment values.
Could you please help me figuring out what I'm doing wrong?
Thanks in advance,
Andrea
ContentView.swift
KApp.swift
TipView.swift