Hello,
I have a SwiftUI application with a Core Data model. This model contains some entities, with properties. The canvas is working as expected, showing the preview.
But whenever I add a new entity, event without any property, the canvas fail to show the preview (event a basic view with only a text view in it). The error message is the following:
Cannot preview in this file - The operation couldn't be completed. Transaction failed. Process failed to launch. I tried to clean my cache, the derived data folder, reset the simulators, etc. When I click on Diagnostics, here is the message:
Error Domain=FBProcessExit Code=4 "The process crashed." UserInfo={NSLocalizedFailureReason=The process crashed., BSErrorCodeDescription=crash, NSUnderlyingError=0x600002f29dd0 {Error Domain=signal Code=4 "SIGILL(4)" UserInfo={NSLocalizedFailureReason=SIGILL(4)}}} RemoteHumanReadableError: The operation couldn’t be completed. Transaction failed. Process failed to launch. (process launch failed) BSTransactionError (1):
==error-description: Process failed to launch.
==precipitating-error: Error Domain=FBProcessExit Code=4 "The process crashed." UserInfo={NSLocalizedFailureReason=The process crashed., BSErrorCodeDescription=crash, NSUnderlyingError=0x600002f29dd0 {Error Domain=signal Code=4 "SIGILL(4)" UserInfo={NSLocalizedFailureReason=SIGILL(4)}}}
==NSLocalizedFailureReason: Transaction failed. Process failed to launch. (process launch failed)
==transaction: <FBApplicationProcessLaunchTransaction: 0x60000186d960>
==error-reason: process launch failed Any idea why I have that?
Thanks,
Axel
PS: I'm using Xcode 12 beta 6 (also tried on beta 5). I'm on macOS Big Sur (20A5364e).
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello,
I'm implementing Sign In With Apple in a SwiftUI application (iOS 14, SwiftUI 2). I'm importing the AuthenticationServices framework. The app build successfully, and can run on an iOS device or simulator. But I cannot preview the view in the Preview / Canvas (it would be easier to design the view).
Cannot find 'SignInWithAppleButton' in scope
Any idea why?
Thanks
Axel
PS: Xcode 12 beta 6, macOS Big Sur beta 5
Hello,
I'm currently adding StoreKit 2 into my app. I've watched the WWDC21 session (Meet SK2) and downloaded the sample SKDemo app. When I want to test the Ask To Buy flow, it does not work: I see the sheet on the device, I see the alert and tap on the "Ask" button. In Xcode, I then approve the transaction but the func listenForTransactions() -> Task<Void, Error> is never called. I'm testing the app in Debug mode, on a real device and on a simulator (using the Products.storekit local configuration file).
What's wrong?
Thanks,
Axel
Version 13.2 beta 2 (13C5081f)
iOS 15.2 (19C5044b)
func listenForTransactions() -> Task<Void, Error> {
return Task.detached {
for await result in Transaction.updates {
do {
let transaction = try self.checkVerified(result)
await self.updatePurchasedIdentifiers(transaction)
await transaction.finish()
} catch {
print("Transaction failed verification")
}
}
}
}
When dealing with auto-renewable subscriptions, there are multiple ways to access the latest transaction. We can access it when a purchase is made, or we can request the latest transaction for a given productID at a later time. To do so, we can use Transaction.latest(for:), access the transaction history using Transaction.all, get the currentEntitlements, or use the array of Product.SubscriptionInfo.Statusthan contains the latest transaction for a subscription group. It's also necessary to listen to transactions when the app is running using the AsyncSequenceTransaction.updates`.
In my app (and also in the SKDemo project from Apple), when I want to access the latest transaction as soon as the app is launched, it's missing the transactions that renewed or happened while the app was not running. I tried using the different methods mentioned above but they never give me the latest transaction, always the latest transaction while the app was running before I killed it. I have to wait for a new renewal event to receive the latest transaction in the Transaction.updates listener, which is not good. For example, when I set the Subscription Renewal Rate to Monthly Renewal Every 30 seconds, and I quit the app when the latest transactionId is 100, I wait for 5 minutes, I expect to see the transactionId 110 but I see 100. In the real life, it means that if the app is not running when a monthly or annual subscription renews, I have to wait weeks or months to receive the missing transaction. I thought that the Transaction.updates listener would be called at launch with all the transactions that occurred while the app was not running.
Is that a bug in Xcode or have I misunderstood something? How can I access the real latest transaction that happened when the app was not running at launch? I need to access that to know what the user has access to. I think the transaction management panel from Xcode displays all the transactions, even the one when the app was not running.
PS: I'm using Xcode 13.2.1 and iOS 15.0 (simulator). Transaction.updates is not working on iOS 15.2 (my device, or simulator) from what I've seen so far.
I’m currently migrating my app to use the concurrency model in Swift. I want to serialize Tasks to make sure they are executed one after the other (no paralellism). In my use case, I want to listen to notifications posted by the NotificationCenter and execute a Task every time a new notification is posted. But I want to make sure no previous task is running. It's the equivalent of using an OperationQueue with maxConcurrentOperationCount = 1.
For example, I’m using CloudKit with Core Data in my app and I use persistent history tracking to determine what changes have occurred in the store. In this Synchronizing a Local Store to the Cloud Sample Code, Apple uses an operation queue for handling history processing tasks (in CoreDataStack). This OperationQueue has a maximum number of operations set to 1.
private lazy var historyQueue: OperationQueue = {
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
return queue
}()
When a Core Data notification is received, a new task is added to this serial operation queue. So if many notifications are received, they will all be performed one after the other one in a serial way.
@objc
func storeRemoteChange(_ notification: Notification) {
// Process persistent history to merge changes from other coordinators.
historyQueue.addOperation {
self.processPersistentHistory()
}
}
In this Loading and Displaying a Large Data Feed Sample Code, Apple uses Tasks to handle history changes (in QuakesProvider).
// Observe Core Data remote change notifications on the queue where the changes were made.
notificationToken = NotificationCenter.default.addObserver(forName: .NSPersistentStoreRemoteChange, object: nil, queue: nil) { note in
Task {
await self.fetchPersistentHistory()
}
}
I feel something is wrong in the second project as Tasks could happen in any order, and not necessarily in a serial order (contrary to the first project where the OperationQueue as a maxConcurrentOperationCount = 1).
Should we use an actor somewhere to make sure the methods are serially called?
I thought about an implementation like this but I’m not yet really comfortable with that:
actor PersistenceStoreListener {
let historyTokenManager: PersistenceHistoryTokenManager = .init()
private let persistentContainer: NSPersistentContainer
init(persistentContainer: NSPersistentContainer) {
self.persistentContainer = persistentContainer
}
func processRemoteStoreChange() async {
print("\(#function) called on \(Date.now.formatted(date: .abbreviated, time: .standard)).")
}
}
where the processRemoteStoreChange method would be called by when a new notification is received (AsyncSequence):
notificationListenerTask = Task {
let notifications = NotificationCenter.default.notifications(named: .NSPersistentStoreRemoteChange, object: container.persistentStoreCoordinator)
for await _ in notifications {
print("notificationListenerTask called on \(Date.now.formatted(date: .abbreviated, time: .standard)).")
await self.storeListener?.processRemoteStoreChange()
}
}
Topic:
App & System Services
SubTopic:
iCloud & Data
Tags:
Core Data
wwdc21-10194
wwdc21-10017
wwdc21-10019
Hello,
I'm trying to clear the purchase history made with a sandbox Apple ID on my test device but it does not work. The past purchases are still returned by StoreKit. I've waited many hours but it seems to persist.
When I use for await result in Transaction.currentEntitlements { in my app, my non-consumable product is still here.
Is it expected?
How long should it take to reset the history?
Is is supposed to work also for non-consumable products?
Thanks
Axel
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
App Store Connect
Subscriptions
In-App Purchase
StoreKit
Hello,
When 'Ask To Buy' is enabled, and the user cancels the request (left button on the provided screenshot below), the purchaseResult in iOS 15 is set to .pending when we call try await product.purchase(). It's wrong, it should be set to .userCancelled because the parent will never receive any approval request in this case. It breaks the logic in my app because tracking real pending requests is then not possible.
I also think that a declined transaction should be made available to the app in the transactions observer: how can we remove a pending transaction that had been declined? We can't for the moment.
Thanks,
Axel
Hello,
I want to access the latest transaction for a Subscription Group. I use the following method static func status(for groupID: String) async throws -> [Product.SubscriptionInfo.Status] to access the statuses for the group, and from there, I can get a verified transaction from the status.
But when I set the GroupID equal to the Subscription Group Reference Name I put in the .storekit configuration file in Xcode, I don't have any status (so wrong ID). Actually, I have to use a subscriptionGroupID like 3F19ED53 (found using a previous transaction: https://developer.apple.com/documentation/storekit/transaction/3749718-subscriptiongroupid).
When I look into a Product, this ID is set for subscriptionFamilyId.
So my question is how can I know the ID if it's not the one I provided in App Store Connect or the config file? Do I first have to access a Product from this group?
Thanks.
I'm not a member of any Family in iCloud. I want to understand what happens when a user is subscribed through Family Sharing but also how to use StoreKit when the user is subscribed twice: as an individual who purchased the product and as a member of a family when the purchase is shared with him.
How can I test Family Sharing for an app offering a product with Family Sharing enabled? Is it possible to create a fake Family in App Store Connect and add testers to it?
I'm using NSPersistentCloudKitContainer with Core Data and I receive errors because my iCloud space is full. The errors printed are the following: <CKError 0x280df8e40: "Quota Exceeded" (25/2035); server message = "Quota exceeded"; op = 61846C533467A5DF; uuid = 6A144513-033F-42C2-9E27-693548EF2150; Retry after 342.0 seconds>.
I want to inform the user about this issue, but I can't find a way to access the details of the error. I'm listening to NSPersistentCloudKitContainer.eventChangedNotification, I receive a error of type .partialFailure. But when I want to access the underlying errors, the partialErrorsByItemID property on the error is nil.
How can I access this Quota Exceeded error?
import Foundation
import CloudKit
import Combine
import CoreData
class SyncMonitor {
fileprivate var subscriptions = Set<AnyCancellable>()
init() {
NotificationCenter.default.publisher(for: NSPersistentCloudKitContainer.eventChangedNotification)
.sink { notification in
if let cloudEvent = notification.userInfo?[NSPersistentCloudKitContainer.eventNotificationUserInfoKey] as? NSPersistentCloudKitContainer.Event {
guard let ckerror = cloudEvent.error as? CKError else {
return
}
print("Error: \(ckerror.localizedDescription)")
if ckerror.code == .partialFailure {
guard let errors = ckerror.partialErrorsByItemID else {
return
}
for (_, error) in errors {
if let currentError = error as? CKError {
print(currentError.localizedDescription)
}
}
}
}
} // end of sink
.store(in: &subscriptions)
}
}
Xcode Version 13.3 beta 3 (13E5104i) or Version 13.2.1
(13C100)
When I add a dictionary to the Info.plist file from the Info tab in the project (for example with the Privacy - Location Temporary Usage Description Dictionary key), Xcode immediately crashes with the following message, that seems to be related to the type of new item added.
ASSERTION FAILURE in /Library/Caches/com.apple.xbs/Sources/DVTFrameworks/DVTFrameworks-20084/DVTFoundation/MacroExpansion/DVTMacroDefinitionTable.mm:1034
Details: value must be nil, string or array, but is {
}
Object: <DVTMacroDefinitionTable: 0x7fe3afb62ce0>
Method: -_setLiteralValue:forMacroName:conditionSet:wantsCheckForDVTMacroExpansionConformance:
Thread: <_NSMainThread: 0x7fe3c480ed70>{number = 1, name = main}
Open FDs: 70/7168
Hints:
Backtrace:
0 -[IDEAssertionHandler handleFailureInMethod:object:fileName:lineNumber:assertionSignature:messageFormat:arguments:] (in IDEKit)
1 _DVTAssertionHandler (in DVTFoundation)
2 _DVTAssertionFailureHandler (in DVTFoundation)
3 -[DVTMacroDefinitionTable _setLiteralValue:forMacroName:conditionSet:wantsCheckForDVTMacroExpansionConformance:] (in DVTFoundation)
4 -[DVTMacroDefinitionTable setLiteralValue:forMacroName:conditionSet:] (in DVTFoundation)
5 -[DVTMacroDefinitionTable setObject:forKeyedSubscript:] (in DVTFoundation)
6 __52-[PBXTarget _adjustBuildSettingsForProductSettings:]_block_invoke (in DevToolsCore)
7 __NSDICTIONARY_IS_CALLING_OUT_TO_A_BLOCK__ (in CoreFoundation)
8 -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] (in CoreFoundation)
9 -[PBXTarget _adjustBuildSettingsForProductSettings:] (in DevToolsCore)
10 -[PBXTarget writeProductSettings:configuration:] (in DevToolsCore)
11 -[PBXTarget setProductSettings:configuration:] (in DevToolsCore)
12 -[PBXTarget setProductSettings:] (in DevToolsCore)
13 -[Xcode3ExtensionBasedInfoController setInfoDictionary:] (in Xcode3UI)
14 -[NSObject(NSKeyValueObservingPrivate) _changeValueForKeys:count:maybeOldValuesDict:maybeNewValuesDict:usingBlock:] (in Foundation)
15 -[NSObject(NSKeyValueObservingPrivate) _changeValueForKey:key:key:usingBlock:] (in Foundation)
16 _NSSetObjectValueAndNotify (in Foundation)
17 __35-[Xcode3InfoEditor _createSubviews]_block_invoke (in Xcode3UI)
18 -[DVTObservingBlockToken observeValueForKeyPath:ofObject:change:context:] (in DVTFoundation)
19 NSKeyValueNotifyObserver (in Foundation)
20 NSKeyValueDidChange (in Foundation)
21 NSKeyValueDidChangeWithPerThreadPendingNotifications (in Foundation)
22 -[Xcode3InfoDictionarySliceController _mergeInfoDictionaries] (in Xcode3UI)
23 -[Xcode3InfoDictionarySliceController customPlistChanged:] (in Xcode3UI)
24 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ (in CoreFoundation)
25 ___CFXRegistrationPost_block_invoke (in CoreFoundation)
26 _CFXRegistrationPost (in CoreFoundation)
27 _CFXNotificationPost (in CoreFoundation)
28 -[NSNotificationCenter postNotificationName:object:userInfo:] (in Foundation)
29 -[Xcode3InfoEditorPlistDocument propertyListChanged:] (in Xcode3UI)
30 -[DVTPlistModel _setPlistNoCopy:forKeyPath:atIndex:doReplace:doNotify:] (in DVTKit)
31 -[DVTPlistModel setKey:forPlist:] (in DVTKit)
32 -[DVTPlistModel setLocalizedKey:forPlist:] (in DVTKit)
33 -[DVTPlistViewController outlineView:setObjectValue:forTableColumn:byItem:] (in DVTKit)
34 -[NSOutlineView _dataSourceSetValue:forColumn:row:] (in AppKit)
35 -[NSTableView _setNewObjectValueFromCell:ifNotEqualTo:forTableColumn:row:] (in AppKit)
36 -[NSTableView textDidEndEditing:] (in AppKit)
37 -[DVTPlistOutlineView textDidEndEditing:] (in DVTKit)
38 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ (in CoreFoundation)
39 ___CFXRegistrationPost_block_invoke (in CoreFoundation)
40 _CFXRegistrationPost (in CoreFoundation)
41 _CFXNotificationPost (in CoreFoundation)
42 -[NSNotificationCenter postNotificationName:object:userInfo:] (in Foundation)
43 -[NSTextView(NSSharing) resignFirstResponder] (in AppKit)
44 -[NSWindow _realMakeFirstResponder:] (in AppKit)
45 -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] (in AppKit)
46 -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] (in AppKit)
47 -[NSWindow(NSEventRouting) sendEvent:] (in AppKit)
48 -[IDEWorkspaceWindow sendEvent:] (in IDEKit)
49 -[NSApplication(NSEvent) sendEvent:] (in AppKit)
50 -[IDEApplication sendEvent:] (in IDEKit)
51 -[NSApplication _handleEvent:] (in AppKit)
52 -[NSApplication run] (in AppKit)
53 -[DVTApplication run] (in DVTKit)
54 NSApplicationMain (in AppKit)
55 start (in dyld)
ProductBuildVersion: 13E5104i
abort() called
Hello,
I'm currently developing an app using SwiftData.
I want the app to use CloudKit to sync data, so I made sure all my model properties are optional.
I've defined a Codable enum as follows:
enum Size: Int, Codable {
case small
case medium
case large
}
I've defined a Drink SwiftData model as follows:
@Model
class Drink {
var name: String?
var size: Size?
init(
name: String? = nil,
size: Size? = nil
) {
self.name = name
self.size = size
}
}
In one of my Views, I want to use a @Query to fetch the data, and use a Predicate to filter the data. The Predicate uses the size enumeration of the Drink model. Here is the code:
struct DrinksView: View {
@Query var drinks: [Drink]
init() {
let smallRawValue: Int = Size.small.rawValue
let filter: Predicate<Drink> = #Predicate<Drink> { drink in
if let size: Size = drink.size {
return size.rawValue == smallRawValue
} else {
return false
}
}
_drinks = Query(filter: filter)
}
var body: some View {
List {
ForEach(drinks) { drink in
Text(drink.name ?? "Unknown Drink")
}
}
}
}
The code compiles, but when I run the app, it crashes with the following error:
Thread 1: Fatal error: Couldn't find \Drink.size!.rawValue on Drink with fields [SwiftData.Schema.PropertyMetadata(name: "name", keypath: \Drink.name, defaultValue: nil, metadata: nil), SwiftData.Schema.PropertyMetadata(name: "size", keypath: \Drink.size, defaultValue: nil, metadata: nil)]
How can I filter my data using this optional variable on the Drink model?
Thanks,
Axel
Hello,
My app uses Core Location to request for Points Of Interest near the user. I used the different APIs provided by Apple: MKLocalPointsOfInterestRequest, MKLocalSearch.Request and MKLocalSearchCompleter. They do not provide the same results at all, whereas the configurations for the requests are very similar.
The MKLocalPointsOfInterestRequest provides very few places (if any, sometimes The operation couldn’t be completed. (MKErrorDomain error 4.) The others give more results but not identical. The code for the different requests is provided below.
Is this the expected behaviour?
If no, have I missed something?
Is this a bug?
Thanks
PS: Tested on Xcode 14.3, iOS 16.0.
MKLocalPointsOfInterestRequest
let center: CLLocationCoordinate2DMake = CLLocationCoordinate2DMake(41.38891, 9.16205)
let poiRequest: MKLocalPointsOfInterestRequest = MKLocalPointsOfInterestRequest(center: coordinate, radius: 3_000)
poiRequest.pointOfInterestFilter = MKPointOfInterestFilter(including: [.beach])
let poiSearch: MKLocalSearch = MKLocalSearch(request: poiRequest)
let resultsPOI = try await poiSearch.start()
print(resultsPOI.mapItems.compactMap(\.name))
This give me the following result:
["Plage de Stagnolu"]
MKLocalSearch.Request
let center: CLLocationCoordinate2DMake = CLLocationCoordinate2DMake(41.38891, 9.16205)
let searchRequest: MKLocalSearch.Request = MKLocalSearch.Request()
searchRequest.region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 4_000, longitudinalMeters: 4_000)
searchRequest.pointOfInterestFilter = MKPointOfInterestFilter(including: [.beach])
searchRequest.resultTypes = .pointOfInterest
searchRequest.naturalLanguageQuery = "beach"
let search: MKLocalSearch = MKLocalSearch(request: searchRequest)
let results = try? await search.start()
print(results.mapItems.compactMap(\.name))
This give me se following results.
["Plage du Petit Sperone", "Plage de 3 Pointes", "Plage de Saint-Antoine Bonifacio", "Plage de Fazzio", "Piantarella Beach", "Plage du Grand Sperone", "Capu Testagro", "Plage de Balistra", "Plage de Stagnolo", "Plage de Cala Longa", "Plage de La Tonnara", "Plage Porto Novo", "Plage de Sant\'Amanza", "Rena Majori", "Plage de Rondinara", "Plage de Santa Giulia", "Spiaggia Rena Bianca", "Plage De Roccapina", "Cala Spinosa", "Naracu Nieddu Beach", "Porto Cervo Beach", "Lido Dog Beach", "Plage de Figari", "Capocchia Du Purpu", "Spiaggia Zia Culumba"]
MKLocalSearchCompleter
func search(coordinate: CLLocationCoordinate2D) {
completer.region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 4_000, longitudinalMeters: 4_000)
completer.pointOfInterestFilter = MKPointOfInterestFilter(including: [.beach])
completer.resultTypes = .pointOfInterest
completer.queryFragment = "beach"
}
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
print(completer.results.map(\.title))
}
This give me the following result:
["Porto Istana Beach", "Sandbanks Beach", "Spiaggia La Cinta", "Piantarella Beach", "Platja de la Barceloneta", "Whitstable Beach", "West Wittering Beach", "Cala Millor"]
Hello,
I've noticed the prices of my products in my Xcode synced StoreKit configuration are not updated when I change the price in App Store Connect. I tried to manually sync the file, to remove and add it again to my project but old initial prices are still used.
In the screenshot below, the price is currently $2.99 but the file still uses the initial price of $1.99. It makes testing a little bit painful because I'm never sure which product is being shown.
Is this a bug?
Is there a way to get the live production App Store prices be used instead of the starting prices?
I filed a feedback for this: FB17798486
Regards,
Axel
Topic:
Developer Tools & Services
SubTopic:
Xcode
Tags:
StoreKit Test
StoreKit
App Store Connect
Xcode
Hello,
I'm trying to understand how dangerous it is to read and/or update model properties from a thread different than the one that instantiated the model.
I know this is wrong when using Core Data and we should always use perform/performAndWait before manipulating an object but I haven't found any information about that for SwiftData.
Question: is it safe to pass an object from one thread (like MainActor) to another thread (in a detached Task for example) and manipulate it, or should we re fetch the object using its persistentModelID as soon as we cross threads?
When running the example app below with the -com.apple.CoreData.ConcurrencyDebug 1 argument passed at launch enabled, I don't get any Console warning when I tap on the "Update directly" button. I'm sure it would trigger a warning if I were using Core Data.
Thanks in advance for explaining.
Axel
--
@main
struct SwiftDataPlaygroundApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(for: Item.self)
}
}
}
struct ContentView: View {
@Environment(\.modelContext) private var context
@Query private var items: [Item]
var body: some View {
VStack {
Button("Add") {
context.insert(Item(timestamp: Date.now))
}
if let firstItem = items.first {
Button("Update directly") {
Task.detached {
// Not the main thread, but firstItem is from the main thread
// No warning in Xcode
firstItem.timestamp = Date.now
}
}
Button("Update using persistentModelID") {
let container: ModelContainer = context.container
let itemIdentifier: Item.ID = firstItem.persistentModelID
Task.detached {
let backgroundContext: ModelContext = ModelContext(container)
guard let itemInBackgroundThread: Item = backgroundContext.model(for: itemIdentifier) as? Item else { return }
// Item on a background thread
itemInBackgroundThread.timestamp = Date.now
try? backgroundContext.save()
}
}
}
}
}
}
@Model
final class Item: Identifiable {
var timestamp: Date
init(timestamp: Date) {
self.timestamp = timestamp
}
}