Archive for August 22, 2015

Saturday, August 22, 2015 [Tweets] [Favorites]

Checking for El Capitan

Jeff Johnson:

If you’re running on OS X 10.10.2 or later, the code tells you that you’re running on OS X 10.11. What happened? Let’s look at <AppKit/NSApplication.h> from the 10.11 SDK:

#define NSAppKitVersionNumber10_10 1343

So far, so good.

#define NSAppKitVersionNumber10_10_2 1344
#define NSAppKitVersionNumber10_10_3 1347

WHUT.

So yeah, instead of increasing the fractional part of the constant for 10.10.2 and 10.10.3, they increased the integer part. Sigh.

Update (2015-08-22): My solution is to check whether I’m running Mac OS X 10.10.0 or later, and then use -[NSProcessInfo isOperatingSystemAtLeastVersion:].

Git as a Document Format

Wil Shipley:

Undo and redo was sort of part of Core Data, but they tried to do it at the lowest level, where any time you changed the database, it just registered an undo event. This turned out to be a horrible idea. If you do any kind of housekeeping such as storing the user’s window position in the database, that suddenly becomes undoable. So, it turns out, if you have any auxiliary objects that get created, that also turns undoable. It’s not a good way to do undo.

[…]

In our perfect world of documents, we want fast loads. We don’t want to be forced to load all our data at once. We want fast saves. Fast is going to be one of the themes of our perfect world. Again we don’t want to re-save large blobs, and we’d love to have an editable format. We want autosaves to be instant, but not blow away the previous states of the document like Preview does. Undo and redo also need to be instant and never be corrupted by bad coding. We’d like them to be persistent, because that’s really cool and provides the ability to prune them.

For security reasons, you don’t necessarily want every version of your document in the document; we’ve learned that from the Microsoft Word exploits. The backup of our perfect file format should play nicely with Time Machine, which means that it shouldn’t have one giant monolithic file that changes by one byte and restarts the backup process. And, it should be incredibly easy to implement, because this is our perfect world, so why not?

[…]

As I said, you still need to decide on the file format for the control files; Git isn’t a file format that you would parse and turn into a series of drawing commands, it just gives you the files and their blobs really easily.

Lazy Filters and Maps

David Owens II:

Simply wrapping items in a lazy() call will convert our Sequence into a LazySequence. This gives us the performance benefits of the more iterative-style approach with the benefits of the semantically broken out operations.

Joe Groff:

map and filter produce copies which are likely cause of slowdown. lazy().map and filter should be as fast as loops.

Marcin Krzyzanowski:

I believe you, but I’m looking at map vs for-loop code in the very moment where loop is many times faster than lazy map.

Swift Funtime

Boris Bügling:

This talk will quickly revisit what we loved about the Objective-C runtime and then explore if/how those things are possible in Swift. It will dive into how to do dynamic introspection, changing behaviour and inspecting private API is still possible or why it is not. In addition to that, the audience will also learn a bunch about Swift under the hood and how using pure Swift or Objective-C compatible objects differ in practice.

Making Tab-Switching and Scrolling Faster in OmniFocus for Mac

Brent Simmons:

Setting up and tearing down the KVO observations isn’t a big deal, though. I was wrong about that. Updating the contents of a cell view is a big deal, however, and this is done when cells are recycled — but this is mainly a big deal because it triggers layout, which is slow.

So here’s what Instruments told me: NSStackView is slow (at least in our case).

But it also told me something else that completely surprised me: the app was spending a whole bunch of time setting and tearing down NSTrackingAreas.

He also replaced -enumerateObjectsUsingBlock: with a for loop.