I'm running into the same problem in my app. The proposed solution of using a @State variable isn't easily possible for me, as while I am using SwiftUI for the front-end of the app, I've isolated the SwiftData utility into an external package.
I'm getting a crash only in the iOS 18 betas, on device and in the simulator.
This model instance was destroyed by calling ModelContext.reset and is no longer usable. PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://F5001085-8312-4E76-9730-25A81E049FB0/SentPostcard/p1), implementation: SwiftData.PersistentIdentifierImplementation)
Post
Replies
Boosts
Views
Activity
I have submitted a related post on my App Clip also being in the "received" status , with the additional steps that I have taken to debug it, and filed FB15052582.
I am experiencing the same issue, but have another piece of the puzzle. I'm using StoreKit2 in a common component across a SwiftUI app and a Share Extension. The latter necessitates that it is a UIKit controller that then loads and calls out to the common SwiftUI components. To put it another way, the UIKit extension does nothing except handle files shared into it, and then passing the data to the appropriate SwiftUI view(s).
Anyway, my common purchase button, which has worked in both contexts for months, now all of a sudden stopped working in the UIKit extension context. Nothing about these have changed, and I know the purchase code works because the same button is used in the SwiftUI app when not running as an extension, and works fine.
The error I'm getting is the same as the parent more or less: "Could not find a UI anchor for purchase." In my UIKit code, I define anchors like this to spawn the SwiftUI view:
// Method to display SwiftUI View initially with placeholder content
private func showSwiftUIView(with imageData: ImageData) {
// Create the SwiftUI content view
let contentView = QuickSendApp(imageData: imageData)
// Wrap it in a hosting controller
let hostingController = UIHostingController(rootView: contentView)
// Add the hosting controller as a child
addChild(hostingController)
// Add the hosting controller's view as a subview
hostingController.view.frame = view.bounds
hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(hostingController.view)
// Notify the hosting controller that it was moved to the parent
hostingController.didMove(toParent: self)
// Store a reference to the hosting controller
self.hostingController = hostingController
// Add an observer to close the share extension
NotificationCenter.default.addObserver(forName: NSNotification.Name("close"), object: nil, queue: nil) { [weak self] _ in
self?.closeShareExtension()
}
}
Because I know the purchase handling works fine, I can only assume there's a breakdown here between the SwiftUI code knowing its bounds and where it can run, and the UIKit code defining the frame for it to run within.
Okay, I found a workaround for my app at least. Here's the situation:
Existing structure:
UIKit extension receives shared items and hands them off to a SwiftUI View
SwiftUI view eventually calls an @observable class for handling store actions like purchasing with StoreKit2
@observable class handles purchasing, and fires notifications for other parts of the app to process.
New structure:
unchanged UIKit extension receives shared items and hands them off to a SwiftUI View
SwiftUI uses the purchaseAction api with the environment @Environment(\.purchase) private var purchase: PurchaseAction setup to handle purchasing. The PurchaseResult is generated, and then passed off to the existing @observable class.
@observable class receives the PurchaseResult, and fires notifications for other parts of the app to process.
The above made it so that my app works re: in-app purchases via an extension again, and continues to work in the SwiftUI-only version of the app.