Archive for February 18, 2020

Tuesday, February 18, 2020

Catalina Data Protections Break File Sharing


The new data protections in Catalina make some folders inaccessible by default (for example the ‘Documents’ folder). When an application tries to access one of these folders the OS presents the user with a dialog box to ensure they intended the access.

This seems to have had the effect of breaking home folder network shares. If you enable file sharing in macOS, any registered user is able to access their home folder using their own credentials. This works in Catalina, but the special private folders (Documents, Downloads, Desktop) can’t be interacted with. Attempts to interact with them result in an ‘access denied’ error and no dialog is presented to the user on the server machine that would allow access. On the client machine, in both Finder and Terminal these folders simply appear empty and you get a permissions error if you attempt to create a file.

You log into your Mac with file sharing but can’t access your own folders. The server Mac doesn’t prompt to allow access, and there doesn’t seem to be a way to manually grant it. I found that sometimes toggling file sharing off and then on again helps. But this may not be easy to do while you’re sitting at the client Mac. And the problem eventually comes back.


iOS Optimization Tips

Rony Fadel (tweet):

We’re tempted to think of labels as lightweight in terms of memory usage. In the end, they just display text. UILabels are actually stored as bitmaps, which could easily consume megabytes of memory.


When you dispatch_async a block onto a concurrent queue, GCD will attempt to find an idle thread in its thread pool to run the block on. If it can’t find an idle thread, it will have to create a new thread for the work item. Quickly dispatching blocks to a concurrent queue could leads to quickly creating new threads.


The concurrent queues you get from dispatch_get_global_queue are bad at forwarding QoS information to the system and should be avoided.


Avoid using dispatch_semaphore_t to wait for asynchronous work


UIKit implements tags using objc_get/setAssociatedObject(), meaning that every time you set or get a tag, you’re doing a dictionary lookup, which will show up in Instruments[…]

Jared Sorge:

I don’t know how many times I have kept text in a label when I perhaps didn’t need to. I also didn’t know that the right place to nil-out text in reusable views (UI{Table|Collection}ViewCell) is not in their prepareForReuse() method but in the delegate’s didEndDisplaying method instead.


Update (2020-02-24): Pierre Habouzit explains how to avoid semaphores (thread):

QoS is a label, its rules of propagation are semi complex, but DO NOT depend on the state of the system.

It’s propagated by only 2 mechanisms (and anything built atop of it), and one secondary obsolete subsystem.


So what you need for priority inversion to kick in, is a wait primitive that has ownership information, IO primitives that record ownership

The list is pretty short:

- pthread mutexes and os unfair locks (and things built on top)

- dispatch_sync() (but for reasons not onto the main queue, but that doesn’t matter for apps)

- xpc_connection_send_with_message_sync()


dispatch_block_wait() isn’t multi-hop. It works for the main thread to wait in certain circumstances (if what you wait on has been asynced before you start to wait on is an important one), because in an app it’s the highest priority you can have, so the likelyhood of requiring more than 1 hop to resolve an inversion is super low. It doesn’t work nearly as well in other cases, for which a better pattern is to share a lock around your work, and have the waiter take that lock to see if the work was done or being done in which case the work will be boosted then. and if it hasn’t been done yet, then do it yourself.

Pierre Habouzit:

If you wait from the main thread, and that the thing you wait on was dispatched onto a serial queue before you wait, then [dispatch_block_wait()] does a good job.

For other more complex cases, use locks the way I explained in the thread.

Goodbye, Mac360

Ron McElfresh:

Mac360 started life back in mid-2004 as a test among friends to get into blogging and to try out Mac OS X Panther Server on an old, unused goose-neck iMac.


Through the years we saw it all. The Mac moved to Intel Inside. The iPhone arrived. The App Store. iPad. Apple Pay, Apple Music, AirPods, and much more. We saw Apple’s stock price and valuation rise to record levels. We graced Mac360 with advertising to help pay some bills and give the growing staff an incentive to continue to write about all things Apple.


Yes, all good things come to an end.

A few years ago I came down with an odd neuromuscular disorder that has slowly become debilitating. After 18 months of tests with a dozen different doctors I was referred to Mayo Clinic in Minnesota. More doctors and extensive tests confirmed a preliminary diagnosis of ALS.

Thanks to Ron and crew for all they’ve done. I hope there’s a way to preserve the archive.

Via Dave Mark:

Here’s a link to a GoFundMe to help defray Ron’s medical expenses.

YouTube App Ending In-App Purchase

Juli Clover:

YouTube today sent out emails to customers who are subscribed to its YouTube TV service through Apple’s App Store, letting them know that App Store subscriptions are going to be discontinued in March.


The YouTube TV app will need to remove all references to subscribing and signing up from its app when in-app purchases disappear, as Apple does not allow apps to link out to third-party subscription purchase options.

Chris Welch (tweet):

Other streaming TV services like Sling TV and Hulu with Live TV don’t offer in-app subscriptions. (Hulu does for its regular on-demand service, however.)

An increasing number of popular services, including Spotify, have stopped accepting new subscriptions through in-app purchases. But in Spotify’s case, the company allows existing customers to keep paying through Apple.

Apple’s developer terms require a 70 / 30 split in a customer’s first year of paying for a subscription through the App Store. After that, the developer gets 85 percent, and Apple takes 15. YouTube TV regularly costs $49.99, but subscribers who pay through Apple are charged a higher $54.99 to help offset Apple’s rules. But apparently, YouTube no longer wants to bother with that, either.

Even with the multi-year discount and charging iOS users $5 extra, Google was still ending up with less by using IAP. Prioritizing services revenue means Apple gets 30/15% of $0, customers get a worse experience, and Google gets their personal information.

Russell Ivanovic:

Let’s be honest. Apple taking a 30% cut for simply processing a transaction is beyond ridiculous. That it drops to 15% in year 2 isn’t better. Other payment processors charge 2.5% 🤪

Or put another way: if Apple gave you the option to use someone else how many people would keep using their service at the current pricing? If the answer is “almost no one” then it’s not a competitive or good service. It’s a monopoly