Archive for February 12, 2016

Friday, February 12, 2016

iCloud Is Too Opaque

Manton Reece:

Last night, Federico Viticci tweeted that he lost a draft blog post he was working on because of an iCloud problem:

“Just lost 1.5k words I had prepared for tomorrow because I wanted to try iCloud sync instead of Dropbox this week.”

[…]

I hear that people love iCloud Photo Library and Notes, and that the quality of these apps and companion services has significantly improved. That’s great. (I also think that CloudKit is clearly the best thing Apple has built for syncing yet.)

But to me, it doesn’t matter if it’s reliable or fast, or even if it “always” works. It only matters if I trust it when something goes wrong. Conceptually I’m not sure iCloud will ever get there for me.

Update (2016-02-12): Paul Jones:

I migrated to a Dropbox and Adobe Lightroom based workflow because of performance, reliability, power, and predictability. Perhaps Photos is simpler and more convenient for most consumers, but it just is too risky and too opaque for me.

Piezo Exits the Mac App Store

Paul Kafasis:

A major reason for the initial creation of Piezo was our desire to allow recording from other applications on the Mac within the limits of what Apple’s Mac App Store rules allowed. We were pleased to provide audio capture to customers of the Mac App Store, and for a time, things worked just fine. However, Apple eventually began requiring that all applications distributed through the Mac App Store be sandboxed. This was a problem. Piezo’s need to capture audio from other applications precludes the possibility of it being sandboxed. This new requirement effectively stopped our ability to upgrade Piezo in any meaningful way.

[…]

We’d like to provide customers with the option of buying Piezo through the Mac App Store, but it’s more important to us that we provide a quality product with full functionality. In the case of Piezo, that now means exclusively distributing the application via our site. Users have always had the option of downloading and buying Piezo direct, so this didn’t involve much in the way of additional work. The biggest issue was simply choosing to remove Piezo from the Mac App Store. Ultimately, we feel the decision was made for us by both technical and bureaucratic factors outside of our control.

Testing NSURLSession With Swift

Joe Masilotti:

Ideally, the interface to NSURLSession would be protocol based. We could create a mock object that conformed to this protocol and use the objects interchangeably under test.

Unfortunately, Apple hasn’t fully embraced protocol-oriented programming in its framework code. No worries; we’ll create our own protocol, and have NSURLSession conform to it via an extension.

[…]

We don’t actually have to implement anything in this extension because we kept the method signature the same as Apple’s framework. Meaning, NSURLSession already implements our protocols required methods.

[…]

The error is occurring because NSURLSession doesn’t have a dataTaskWithURL() method that returns our custom protocol. To fix this, we just need to extend the class a little differently.

[…]

Here we implement the method in the protocol manually. But instead of doing any actual work, we call back to the original implementation and cast the return value. The cast doesn’t need to be implicit because our protocol already conforms to Apple’s data task.

This is a subtle bit of code where the protocol and class have methods with the same name and arguments but different return types. So it’s an overload rather than an override.

Joe Masilotti:

To keep our tests running fast let’s completely flatten the code path. One thread, no asynchronous behavior, no network activity.

[…]

Now we can set what data and/or error is returned from the dataTaskWithURL() method. But wait, that method returns a data task, right? Correct, but look at the last parameter.

The completion handler would normally be called by the API when a real network request returns. We need to replicate this while we build our own mock. To do so, simply call the handler with our “next” variables before returning.

Previously: Swift Protocols.

Update (2016-11-12): Part 3.

Adobe Creative Cloud Installer Deleting Hidden Files

Backblaze (via Jordan Merrick):

We’ve encountered an issue on the Mac where Adobe Creative Cloud appears to be removing the contents of the first hidden folder at the root of the drive, in alphabetic order. By happenstance, the first hidden folder on most Backblaze customer’s internal drive is the .bzvol folder.

As a workaround, they suggest creating a new top-level folder whose contents you don’t care about: /.adobedontdeletemybzvol.

Update (2016-02-12): Brian Webster:

Yup, this happened to me the other day.

Ole Begemann:

Thank you Adobe for making all your installers require admin privileges.

Daniel Jalkut:

If Apple strived to make the Sandbox fulfill more needs, I think many more apps would be sandboxed.

OS X would be a more secure platform if developers could sandbox, declaring ALL their behaviors, whether they fit long-term goals or not.

In this scenario, an app like Adobe’s might have “I need to delete /.adobe”, and the system would prevent it deleting /.bzvol.

Because Apple’s sandboxing limitations are so rigid, some developers who would otherwise “do the right thing” won’t even bother trying.

Update (2016-02-13): Wil Shipley:

Adobe Creative Cloud is a great example of why Apple’s sandbox is nigh-useless. Because Adobe only sells it direct, so no sandbox.

Small developers are stuck in a barely functioning, almost impossible to use sandbox while one of the largest is deleting our files.

Update (2016-02-16): Adobe:

Earlier today we were notified of an issue with an update to the Creative Cloud Desktop application on Mac that we rolled out earlier in the week. In a small number of cases, the updater may incorrectly remove some files from the system root directory with user writeable permissions.

We have removed the update from distribution, and are in the process of deploying a new update which addresses the issue. When prompted for the update, Creative Cloud members should install it as normal.

Backblaze:

Adobe fixed the issue on Sunday with version (3.5.1.209). All users of Adobe Creative Cloud can now update their software.

Matt Gemmell:

Creative Cloud pushes the user to enable auto-updating, and many people opt-in for the sake of convenience. It’s a fine idea, and ordinarily it should increase security and stability too, but more importantly it’s a gesture of trust. When that trust is violated, the damage done to the vendor’s image and their relationship with the customer is severe. Adobe has a long history of Byzantine installations and concomitant problems, and this one takes the cake – especially from a large company which readily has the resources for extensive QA, and a great deal to lose.

Update (2016-02-18): John Siracusa, like me, argues that Apple should make it as easy as possible for developers to sandbox all applications, even those that won’t be in the Mac App Store.

Concurrent Memory Deallocation in the Objective-C Runtime

Mike Ash (comments):

For our own apps we can test and tune the caches to avoid this, but the Objective-C runtime doesn’t have this option. Because the method cache is so critical to performance, and because each entry is relatively small, the runtime doesn’t impose any size limit on the caches, and expands them as necessary to cache all messages that have been sent.

Note that the caches do sometimes get flushed; any time something happens that might cause the cached data to become stale, such as loading new code into the process or modifying a class’s method lists, the appropriate caches are destroyed and allowed to refill.

[…]

Note that there is no need to block execution of objc_msgSend for this to work properly. Once the cache free code is sure that nothing is in objc_msgSend at any particular moment after it has replaced the cache pointer, it can go ahead and free the old one. Another thread might call out to objc_msgSend while the old cache pointer is being deallocated, but this new call can’t possibly see the old pointer anymore, so it’s safe.

[…]

The purpose of the hypothetical global counter is to track when any thread is within a particular region of code. Threads already have something that tracks what code they’re currently running: the program counter. This is the CPU register which tracks the memory address of the current instruction. Instead of a global counter, we could check each thread’s program counter to see if it’s within objc_msgSend. If all threads are outside, then it’s safe to free the old caches. […] Then objc_msgSend doesn’t have to do anything special at all. It can access the caches directly without worrying about flagging that access.