Posts

Post not yet marked as solved
20 Replies
I think I was able to solve a similar problem, though my problem was slightly different. The short answer is: use at least a .userInitiated qualityOfService in Catalyst; when the qualityOfService is .default (or below) requests become discretionary when the app is in the background (i.e., inactive). And I think that's where the problem is. For a longer answer, see my response on Stack Overflow.
Post not yet marked as solved
1 Replies
I'm not sure I understand; that's the way it's supposed to work? See the docs for init(dateMatching:repeats:): Discussion If you specify true for the repeats parameter, you must explicitly remove the notification request to stop the delivery of the associated notification. Use the methods of UNUserNotificationCenter to remove notification requests that are no longer needed. So in response to, say, some user action you have to remove the notification yourself.
Post marked as solved
20 Replies
I just ran into a similar problem and discovered that my schemes referenced old configurations, configurations that no longer existed. Once I updated them to the correct configurations the build succeeded.   (I'm leaving this comment about a year later. It's possible that what I ran into is completely different from what was originally reported. Still, it took me quite a while to track the problem down, so I wanted to leave a note that might save others time.)
Post marked as solved
3 Replies
I think I've run into another variation of this (now in Xcode 11.6). I think there are two additional problems. I have two local Swift packages that reference two remote Swift packages. (The remote packages are Apple's SwiftProtobuf and RevenueCat.) When I build for testing, both of the local Swift packages generate errors. The error for the package that references SwiftProtobuf is a compiler error: Command CompileSwift failed with a nonzero exit code The error for the package that references RevenueCat is a linker error: Undefined symbols for architecture x86_64:   "___ubsan_handle_nonnull_arg", referenced from:       -[RCPurchaserInfo setUpDateFormatter] in Purchases.o       -[RCPurchases dispatch:] in Purchases.o   "___ubsan_handle_float_cast_overflow", referenced from:       -[NSDate(RCExtensions) millisecondsSince1970] in Purchases.o   "___ubsan_handle_load_invalid_value", referenced from:       _RCSetShowDebugLogs in Purchases.o       _RCShowDebugLogs in Purchases.o       _RCDebugLog in Purchases.o       _RCErrorLog in Purchases.o       -[RCSystemInfo initWithPlatformFlavor:platformFlavorVersion:finishTransactions:] in Purchases.o       -[RCSystemInfo finishTransactions] in Purchases.o       -[RCSystemInfo setFinishTransactions:] in Purchases.o       ...   "___ubsan_handle_pointer_overflow", referenced from:       ___32-[NSData(RCExtensions) asString]_block_invoke in Purchases.o   "___ubsan_handle_type_mismatch_v1", referenced from:       -[RCInMemoryCachedObject setCacheDurationInSeconds:] in Purchases.o       ___32-[NSData(RCExtensions) asString]_block_invoke in Purchases.o       -[RCSystemInfo setFinishTransactions:] in Purchases.o       -[RCHTTPClient setSystemInfo:] in Purchases.o       -[RCIntroEligibility setStatus:] in Purchases.o       -[RCPurchaserInfo setUpDateFormatter] in Purchases.o       -[RCPurchases allowSharingAppStoreAccount] in Purchases.o       ... ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) Here's the first issue: Both errors seem to be caused by the fact that one of my test configurations uses UBSan. As per the original post, my scheme has two configurations, a default one and one that enables UBSan. Here's the second issue: The errors persist even if I disable the UBSan test configuration. If I turn off UBSan in the (disabled) UBSan test configuration, everything builds and runs successfully.
Post marked as solved
3 Replies
I was able to resolve this. As far as I can tell, it's an Xcode bug.The short version is that Xcode seems to assume that at least one test configuration will use the shared (default) test configuration, unmodified. That assumption can of course be wrong; it's possible that no test configuration exactly matches the defaults. The mistake can prevent Xcode from finding the test target bundles for local Swift Packages.The long version...* A test plan has a shared (default) test configuration.* A test plan has one or more actual test configurations.* Xcode places build products in directories whose names are based on their differences from the shared (default) configuration.* The build products for test configurations that don't have any meaningful differences are placed under the root, e.g.: "/Products/***/...".* The build products for test configurations that do have meaningful differences are placed under subirectories whose names are derived from the differences, e.g.: "/Products/Variant-ASan-UBSan/***/...", "/Products/Variant-UBSan/***/...".* Some part of Xcode assumes that at least one test configuration will match the shared defaults. In other words, some part of Xcode assumes that a test bundle will always exist under the root, in "/Products/***/...".* In my case that wasn't true; my one and only test configuration enabled UBSan. That caused its build products to be placed in "/Products/Variant-UBSan/***/...". So, at least for my local Swift Packages, Xcode was looking in the wrong place: it was looking in the root rather than in a variant subdirectory under the root.* The workaround was to create a test configuration that didn't differ from the default.===As an aside, I mentioned that the local Swift Package targets were listed in the scheme. I eventually realized that that was a hold over from my pre-test plan configuration; that's how I was getting Xcode to test all packages together with the main app before converting. With the test plan in place I no longer need them listed directly in the scheme. Unfortunately, removing them didn't fix my actual problem.
Post not yet marked as solved
3 Replies
Just adding a little more detail...Not surprising: Rather than calling context.refreshAllObjects() you could just call context.refresh(), passing in the object whose derived attribute you're about to access.Surprising: Acquiring an object via an NSFetchRequest doesn't refresh its derived attributes.(The second is surprising to me because I thought that an NSFetchRequest guaranteed a trip all the way to the store—which is, you might think, a kind of refresh.)
Post not yet marked as solved
5 Replies
One last comment...All of my experiments revolve around concurrent changes on disconnected devices. For connected devices most of this won't matter, at least not most of the time.My goal is to understand how things might go sideways—and how sideways they might go. How likely are users to feel/think that they "lost" data when they didn't expect to? How likely am I, as the developer, to understand the actual invariants of the system rather than the invariants I expected?
Post not yet marked as solved
5 Replies
Thanks very much for the links!It's theoretically possible for "last writer wins" to operate at the attribute level, entity level, or change/delta/event level. The example in the video only talked about concurrent changes to the same attribute, so on its own it wasn't enough to answer my question.The choice Apple made, "entity level", I think matches what most people would probably expect by default, with one possibly surprising exception: to-one relationships seem to act like attributes rather than to-many relationships. (Whether or not that's surprising depends, I think, on your default mental model. If you're thinking in terms of "attributes" vs. "relationships", as I was, you might be surprised. If you're thiking in terms of, say, columns and rows in database tables, you might not be.)I'm trying to figure out whether or not I can reason accurately about concurrent changes in such a model. My initial take is that, for the app I'm currently working on, I can't.Domain Driven Design defines the term "aggregate" to mean something like "a set of entities and values that must be kept together in order to maintain system invariants." In Apple's implementation an aggregate would have to be implementable as a single row in a table. If that works for your use case, you're golden. If it doesn't, then you'd have to be willing and able to consider far more "run time states" than you might otherwise expect. That's where the "reason accurately" comes into play: you'd have to be able to anticipate all of those additional states that you didn't think a single user on a single device could introduce, given your UI—for example, a "mismatch" between two one-to-one entities, or a "mismatch" between a master and multiple detail entities. (Inverse relationships might make the reasoning more difficult still, but I haven't experimented with them yet, and don't currently plan to.)Pondering all of this...PS I make no claim that my experimental results are correct. :-) In my current setup the experiments are a bit painful to run. It would be great if someone else was able to confirm my results.
Post not yet marked as solved
5 Replies
One last experiment.3. "last writer wins" with to-one relationships *and* attributes1. Create a Core Data with CloudKit app2. Create two entities, A and B, with a to-one relationship from A to B, and a text attribute in A3. Create two instances of B, b1 and b24. Create an instance of A, a1, with a to-one relationship to b1 and a value of "x" in the text attribute5. Sync across two devices6. Disconnect the two devices from the network7. On device 1, set the text attribute to "y". Save the changes.8. On device 2, set the to-one relationship to b2. Save the changes.9. Reconnect both devices to the network and allow them to sync.10. I believe the final result will be that a1's text attribute is still "x" and to-one relationship is b2, because device 2 saved its changes after device 1. Device 1's change was "lost".===This qualifies as both surprising and not-surprising: to-one relationships act entirely like attributes. (Whether or not it's surprsing depends, I think, on your initial mental model. If you're thinking in terms of "attributes" vs "relationships" you might find it surprising. If you're thinking in terms of "single-valued" vs. "multi-valued" you might not.)===I'm going to stop here because I've learned what I needed to know for my own purposes, but there's at least one additional experiment that would be very valuable to try: how do changes to an inverse relationship interact with changes to an attribute?1. Disconnect the two devices from the network2. On device 1, set a1's text attribute. Save the changes.3. On device 2, set the *inverse* of a1's to-one relationship. Save the changes.4. Reconnect both devices to the network and allow them to sync.Is either change lost? Or are both kept?
Post not yet marked as solved
5 Replies
Two additional experiments.1. "last writer wins" with to-one relationships1. Create a Core Data with CloudKit app2. Create two entities, A and B, with a to-one relationship from A to B3. Create two instances of B, b1 and b24. Create an instance of A, a1, with no to-one relationship5. Sync across two devices6. Disconnect the two devices from the network7. On device 1, set the to-one relationshp to b1. Save the changes.8. On device 2, set the to-one relationship to b2. Save the changes.9. Reconnect both devices to the network and allow them to sync.10. I believe the final result will be that a1's to-one relationship is b2, because device 2 saved its changes after device 1.2. "merge" with to-many relationships1. Create a Core Data with CloudKit app2. Create two entities, A and B, with a to-many relationship from A to B3. Create two instances of B, b1 and b24. Create an instance of A, a1, with no to-many relationship5. Sync across two devices6. Disconnect the two devices from the network7. On device 1, add b1 to a1's to-many relationshp. Save the changes.8. On device 2, add b2 to a1's to-many relationship. Save the changes.9. Reconnect both devices to the network and allow them to sync.10. I believe the final result will be that a1's to-many relationship contains both b1 and b2.===Neither of the above is surprising; I'm just documenting what I'm finding.HOWEVER...I now have a case where device 1 and device 2 no longer have the same contents for a to-many relationship. Since the entire mechanism is a black box I don't know precisely how that happened; I just know that, given the model, it takes some effort to get them back in sync.Using example 2 as a starting point, with both devices sync'd, I have this:1. device 1's instance of a1 has no to-many relationships2. device 2's instance of a1 has b2Oops. Then:1. On device 2, add b1 to a1 and save. (a1 now has b1 and b2)2. On device 1, after sync, a1 now has b1, but it still doesn't have b2.Oops. Then:1. On device 2, remove b2 from a1 and save. (a1 now has b1)2. On device 2, add b2 to a1 and save. (a1 now has b1 and b2)3. On device 1, after sync, a1 finally has both b1 and b2.