Simple Opt Out (via Troy Davis):
Simple Opt Out is drawing attention to opt-out data sharing and marketing practices that many people aren’t aware of (and most people don’t want), then making it easier to opt out. For example:
- Target “may share your personal information with other companies which are not part of Target.”
- Chase may share your “account balances and transaction history … For nonaffiliates to market to you.”
- Crate & Barrel may share “your customer information [name, postal address and email address, and transactions you conduct on our Website or offline] with other select companies.”
Privacy Web
Steffen Ryll:
At WWDC ’17, Apple introduced a number of new Core Data features, one of which is Persistent History Tracking or NSPersistentHistory
. But as of the time of writing, its API is still undocumented. Thus, the only real reference is the What’s New in Core Data WWDC session.
Since Persistent History Tracking makes sharing an NSPersistentStore
across multiple processes and is one of my favorite new Core Data features, it is unfortunate that it mostly seems to fall of the radar.
The purpose of this post is to give a real-world example on how to use it and what makes it so great.
That was written a year and a half ago, and NSPersistentHistory
remains a really cool feature that’s under-discussed and under-documented. Some resources I’ve found are:
Here are some things I figured out by exploring:
- The history is stored directly in the same SQLite database(s) as the persistent store.
- It uses tables that look kind of like Core Data tables, only with a different prefix.
- But you couldn’t create them yourself using Core Data, since the same column can store the primary key for different types of entities (you would think
NSObjectIDAttributeType
could do that, but it actually can’t be used in stores), and likewise for the columns that store the tombstone values.
- The tables are updated using SQLite triggers, which are again not directly exposed in Core Data (though this year’s new derived attributes also use them).
- The triggers are fired for all database changes, so unlike the managed object context’s change tracking, they also work for batch updates and deletions (and, presumably, the forthcoming batch insertions).
- But they don’t tombstone attributes that use
allowsExternalBinaryDataStorage
, even for small values that are stored in the database. In my opinion, Core Data should report an error if you try to use a model that’s configured in this way.
- The tables look very compact, with repeated string values interned and the list of modified columns stored as a bit vector.
- Core Data automatically updates the schema of the history tracking tables when you do a migration.
- Enabling history tracking does not change the version of your model. But, in practice, you’ll get incorrect results if you don’t enable it consistently.
- Setting an attribute to be preserved after deletion (i.e. for the tombstone) does change the model’s version hash, however.
- There’s no public API to set this flag on an attribute in the model, only a checkbox in Xcode. However, you can use key-value coding to set or query
NSPropertyDescription.preserveValueOnDeletionInPersistentHistory
.
- So, overall, it seems tricky to use persistent history on a store that will be shared with OS versions that don’t support history tracking. You might have to roll your own in that case.
- Querying and pruning the history works as you would expect.
- The
NSPersistentHistoryTransaction.objectIDNotification()
does not generate a NSManagedObjectContextDidSaveNotification
, but rather a private NSManagedObjectContextDidSaveObjectIDsNotification
notification.
- Rather than containing full objects under keys like
NSUpdatedObjectsKey
, it contains object IDs under keys like updated_objectIDs
. This is a bit unexpected, because NSManagedObjectContext
is already documented to support NSManagedObjectID
or NSURL
objects under the NSUpdatedObjectsKey
key.
- In any case, you get IDs because it isn’t storing the changed values. Instead, when merging, it fetches the latest values from the store.
- This makes sense given the data model, but it means that, perhaps counterintuitively, merging will update all the attributes, not just those those changed in the transaction that generated the notification. And they’ll be updated to the current values, which may be much newer than the ones at the time of the transaction. This is not version control, just a way to see what has changed.
Update (2019-08-22): Deeje Cooley:
I incorporated Persistent History Tracking into CloudCore, an open-source CoreData-CloudKit sync engine, specifically to support offline sync. Check it out!
Update (2020-09-14): See also: Antoine van der Lee.
Core Data Documentation iOS iOS 11 iOS 12 Key-Value Coding (KVC) Mac macOS 10.13 High Sierra macOS 10.14 Mojave Programming SQLite
Howard Oakley:
If you write scripts of any kind for macOS – shell scripts, AppleScripts, or anything similar – now is the time to join the Catalina beta programme (if you’re not already signed up) if you want those scripts to work with macOS 10.15 when it’s released in a month or so. There are plenty of changes to security and privacy which you’ll need to check out, but my concern in this article is the effect of Catalina’s read-only system volume on paths – a topic which doesn’t seem to have been discussed much, but which may well break many scripts and apps.
[…]
Reality is always more complex than a slide in a WWDC presentation, and there are a great many more folders/directories which are affected by this new division.
[…]
Unfortunately, the illusion created by the Finder is unhelpful for identifying paths to be used in Terminal, scripts or apps: important new paths like /System/Volumes/Data/
aren’t shown there even when you enable the display of hidden items. Indeed, browsing the new folder hierarchy in the Finder looks very clean and simple, but will only cause endless confusion.
Previously:
AppleScript Automator Documentation Finder Mac macOS 10.15 Catalina Programming Unix
Erik Sink:
Bottom line, C# 8.0 uses the same syntax for nullability of reference types that we have been using for value types:
string x; // not nullable
string? y; // nullable
And yes, that means that the meaning of a type declaration like string
(without the ?
) has changed.
Whoa, isn’t that a massive break in compatibility? Actually no. In fact, although this feature looks like a huge breaking change, the entire thing was carefully designed to preserve backward compatibility.
First of all, this whole feature is turned off by default, and has to be explicitly turned on. Second, all it really does is generate warnings.
This seems not that different from nullability in Objective-C, only with cleaner syntax.
C# Programming Language Language Design Programming