Sunday, January 25, 2015

An Example on How to Use NSProgress

Jaanus Kase (via Ole Begemann):

The best I can tell, there is no way to do this in Swift that does not look insane and ridiculous. See, -[NSWindowController initWithWindowNibName:] is a convenience initializer on NSWindowController, and Swift is much more restrictive about its initialization behavior in this case. You can’t call the parent’s convenience initializer from your own designated initializer.

[…]

Now, I was able to fix my demo project because it is a small, tightly controlled thing. I can be pretty sure that no other unwanted stuff is running after I fixed the above (first show window, and only then become the current progress object). But this might not be feasible for bigger projects where more things are happening at the same time and you don’t have tight control over all of them. Like, during the time where you are the current progress object, can you guarantee that nobody in your app is going to read anything from disk?

[…]

I suppose another solution is what Ole describes, to forgo the whole “current progress object” business and just pass the parent around between objects, and you can then become a child of that particular one and not just a child of whatever happens to be “current” at that point. This defeats the “loose coupling” aspect, though.

Too bad—it seemed like such a promising API. He says it’s also crashy.

MPW, Carbon, and Building Classic Mac Apps on Yosemite

Steven Troughton-Smith (via Thomas Brand):

mpw is an m68k binary translator/emulator whose sole purpose is to try and emulate enough of Classic Mac OS to run MPW’s own tools directly on OS X. MPW is unique in that it provided a shell and set of commandline tools on Classic Mac OS (an OS which itself has no notion of shells or commandlines) - this makes it particularly suited to an emulation process like mpw attempts to provide, as emulating a commandline app is a lot easier than one built for UI.

[…]

With the same source file, and only a handful of #ifdefs, I could build the same app for 1984’s System 1.0 all the way up to the current release of OS X, Yosemite.

[…]

Right now [mpw is] a fully usable tool that makes Classic Mac OS compilation possible and easy to do on modern versions of OS X, without requiring emulators or ancient IDEs or the like. To my knowledge, this is the first time this has been possible (excluding legacy versions of CodeWarrior).

Audio Hijack 3

Paul Kafasis:

We’ve been developing products under the Audio Hijack name since 2002, when Mac OS X 10.1 was cutting-edge! Over the years, users have found incredible ways to adapt Audio Hijack for their needs, leading us to make many updates and improvements. Eventually, however, these changes caused Audio Hijack to outgrow our original designs. We’ve incorporated over a decade’s worth of experience and feedback into Audio Hijack 3 to improve the process of recording and enhancing audio. Every aspect of our previous Audio Hijack products has been thoughtfully examined and considered, with enhancements made across the board.

The new interface looks really neat.

Deleting Folders Using the “find” Command

I’ve seen lots of Web pages about how to use the Unix find command to delete files or directories with a certain name. I do this pretty frequently. For example, the Makefile for deploying my apps deletes the Headers folders inside of the embedded frameworks. It also has legacy lines for deleting CVS and .svn folders. The standard advice seems to be to write something like this:

find MyApp.app -name Headers -type d -delete

This looks inside the MyApp.app folder for items named Headers that are directories and deletes them. This works with GNU find, but in the BSD version of find (which ships with Macs) the -delete option only works with files and empty directories. Confusingly, it won’t report failure for a non-empty directory; it will just leave it there. The common solution is to use a command like this:

find MyApp.app -name Headers -type d -exec rm -rf "{}" \;

This executes the rm -r {} command for each found item, with the {} replaced by the item’s path. The \; marks the end of the command and is escaped so that the shell sends the ; to find instead of interpreting it as a command separator. The problem with this version is that it can result in “No such file or directory” errors. find will execute the command for a folder (thus deleting it), then try to recurse into that folder and complain that it doesn’t exist. find succeeded in that all the directories did get deleted—it doesn’t stop when it encounters the first missing directory—but it reports a failing exit status that can halt your shell script or Makefile.

A common way to work around this is to silence the errors. You can use:

find MyApp.app -name Headers -type d -exec rm -rf "{}" \; || true

to make sure that the combined command exits with success. Or, in a Makefile, you can use:

-find MyApp.app -name Headers -type d -exec rm -rf "{}" \;

to tell make to ignore errors. In both cases, the command will succeed, but it will still print “No such file or directory”. So sometimes people silence the error:

-find MyApp.app -name Headers -type d -exec rm -rf "{}" \; 2>/dev/null

My preferred solution is to prevent the error in the first place. You can tell find to do a post-order traversal instead of a pre-order one. In other words, it will recurse first and delete later. This is done by specifying the -d option:

find -d MyApp.app -name Headers -type d -exec rm -rf "{}" \;

You also optimize this somewhat by using + instead of \;. This causes find to send multiple items to a single invocation of the rm command. I’ve also found that, at least with Bash, it is not necessary to quote the braces. This command looks cleaner and works well:

find -d MyApp.app -name Headers -type d -exec rm -rf {} +

Another way to do essentially the same thing is to use xargs:

find -d MyApp.app -name Headers -type d -print0 | xargs -0 rm -rf

In practice, it seems that if you use xargs you don’t need -d. Perhaps this is because a certain amount of find output is buffered before xargs begins deleting. However, I think it is more correct to leave it in.

Update (2015-01-26): As noted in the comments, you can use -prune (instead of -d) to tell find not to recurse into the matching folders that will be deleted anyway:

find MyApp.app -name Headers -type d -prune -exec rm -rf {} +

Saturday, January 24, 2015

Swift Capture Lists

Russ Bishop:

The Language Guide claims you should use unowned if the closure and containing object reference each other and will be destroyed at the same time. Presumably that’s to avoid the cost of safely nil’ing out a weak reference in an object that’s about to dealloc anyway.

Most people aren’t aware that you can create new named values here as well[…]

Documents in the Cloud: bird and brctl

Apple’s site doesn’t yet document them, but bird is the system daemon behind iCloud documents, and brctl is the corresponding control utility (via Zachary Drayer).

Accessibility Showdown: iPhone 6 vs. iPhone 6 Plus

Steven Aquino:

In this context, bigger truly is better: it allows for more content to be shown, and the 401 pixels-per-inch (ppi) screen is so bright and crisp that I find myself rarely squinting to read text. The screen is so good, in fact, that text is easily viewable for me at normal size (my preference, though it can also be set to show less content at larger sizes). The advantages of the iPhone 6 Plus’s screen are such that I experience less eye strain and fatigue than on my iPhone 6, whose screen is “only” 326 ppi.

Alas, the sheer physical size of the iPhone 6 Plus hardware makes for a polarizing user experience. As wonderful as the screen is, the dimensions of the iPhone 6 Plus make me yearn for my smaller iPhone 6. The iPhone 6 Plus is a monster, making it cumbersome both to hold and carry in my pocket. Even getting it in and out of my pocket takes more effort than the iPhone 6, and it’s much more obvious in my pocket as well.

This isn’t just personal preference. Sure, my hands are small, but my cerebral palsy makes holding the iPhone 6 Plus awkward and uncomfortable, forcing me to adjust my grasp constantly to maintain control over the phone. Holding it to my ear during phone calls is hard too, because it’s so smooth and hard to grip, and the size makes it weird to hold against my ear.

The Imitation Game

Scott Aaronson:

OK, so for those who haven’t yet seen it: should you? Here’s my one paragraph summary: imagine that you told the story of Alan Turing—one greatest triumphs and tragedies of human history, needing no embellishment whatsoever—to someone who only sort-of understood it, and who filled in the gaps with weird fabrications and Hollywood clichés. And imagine that person retold the story to a second person, who understood even less, and that that person retold it to a third, who understood least of all, but who was charged with making the movie that would bring Turing’s story before the largest audience it’s ever had. And yet, imagine that enough of the enormity of the original story made it through this noisy channel, that the final product was still pretty good. (Except, imagine how much better it could’ve been!)

Geoff Knauth:

I liked The Imitation Game, despite its problems. Here’s a better list of its inaccuracies than I’d have produced.

Gitlet: Git Implemented in JavaScript

Mary Rose Cook:

Over the last six years, I’ve become better at using Git for version control. But my conceptions of the index, the working copy, the object graph and remotes have just grown fuzzier.

Sometimes, I can only understand something by implementing it. So, I wrote Gitlet, my own version of Git. I pored over tutorials. I read articles about internals. I tried to understand how API commands work by reading the docs, then gave up and ran hundreds of experiments on repositories and rummaged through the .git directory to figure out the results.

I discovered that, if approached from the inside out, Git is easy to understand. It is the product of simple ideas that, when combined, produce something very deep and beautiful.

Creating the Natural Numbers From First Principles

Brandon Williams:

Turns out, natural numbers can be constructed from two basic objects. First, we start with the “smallest” member of the naturals, called Zero. Then we have a function Succ (the successor function) that takes a natural and returns the next natural.

Back to the iPhone 5s

Jeff Hunsberger (via John Gordon):

The iPhone 6 screen always felt a bit like it wasn’t made for my hands like the iPhone 5S was. The iPhone 4 and 4S were tiny and I could easily reach any area of the screen. My resistance to the iPhone 5 gave way to the fact that I could still reach the top left corner while holding my phone in the right hand. The iPhone 6 requires you to shift the phone in your hand, balance it on your fingertips and then stretch across to hit the top left of the screen one-handed. The whole time you are courting disaster.

[…]

Moving back to the iPhone 5S has reaffirmed my feeling that it is the current high point in smartphones. It is the best balance in speed, battery life, size and durability.

When testing an iPhone 6, I found that it was much less comfortable in my jeans pocket. It simply wouldn’t fit in the breast pocket of my ski jacket. I’m hoping that the iPhone 6S will come in a smaller size. Meanwhile, I’m still happy with the 5s.

The Future of No Thirst Software

Kevin LaCoste (tweet):

First off, you can rest easy that updates are already being worked on and roadmaps are being discussed. We have a lot planned for 2015 and beyond starting with some minor updates to get things up-to-date with the latest and greatest on iOS and OS X.

Great news. I had been worried, as I use MoneyWell every day and it had been more than six months since the original developer, Kevin Hoctor, announced his move to Apple. New Kevin’s Twitter is here, and he explains a bit about his bio here.

Friday, January 23, 2015

Let’s Build Swift Notifications

Mike Ash:

NSNotifications are both simple and powerful, which is why they show up so often in the frameworks. Specifically, they have a few distinct advantages:

  1. Loose coupling between notification senders and receivers.
  2. Support for multiple receivers for a single notification.
  3. Support for custom data on the notification using the userInfo property.

There are some disadvantages as well:

  1. Sending and registering for notifications involves interacting with a singleton instance with no clear relationship to your classes.
  2. It’s not always clear what notifications are available for a particular class.
  3. For notifications which use userInfo, it’s not always clear what keys are available in the dictionary.
  4. userInfo keys are dynamically typed and require cooperation between the sender and receiver that can’t be expressed in the language, and messy boxing/unboxing for non-object types.
  5. Removing a notification registration requires an explicit removal call.
  6. It’s difficult to inspect which objects are registered for any given notification, which can make it hard to debug.

My goal in reimagining notifications in Swift is to remedy these problems.

He runs into an interesting case where casting is necessary to satisfy Swift’s type system. I didn’t expect this, and it’s instructive to think about what is going on here. Also note how it transparently handles observer functions with different numbers of parameters.

The Design Philosophy of the DARPA Internet Protocols

Adrian Colyer:

Understanding the underlying principles behind something can turn what might on the surface seem to be simply a collection of facts into a chain of causes and consequences that makes it much easier to see how those parts fit together. Clark provides us with some of those insights for the design of the Internet Protocols, working from the goals towards the implementation consequences.

[…]

The only error the communicating parties should ever see is the case of total partition. If the application(s) on either end of the connection are not required to resolve any other failures, then the state necessary for recovery must be held in the lower layers – but where? One option is to put it in the intermediate nodes in the network, and of course to protect it from loss it must be replicated. I think the knee-jerk reaction of many system designers today might be to distribute the state in some such manner, maybe using a gossip-protocol. But the original designers of the internet had a insight which enabled a much simpler solution, and they called it ‘fate sharing.’

Modern Login Items

Cory Bohon:

Login Items have previously been a way for OS X apps to provide this service to users, but is not compatible with the sandbox requirements of the Mac App Store. Fortunately, there is a much more modern way to handle this, and I’ll walk you through setting it up in your own projects.

[…]

In order to launch our application at login, we’ll create a separate application that is included in the signed main application bundle. The sole purpose and function of this separate application will be to launch our main application at login, if it is not already launched.

[…]

This code uses the ServiceManagement framework’s function called SMLoginItemSetEnabled. The first parameter in this method is a CFString containing the bundle identifier of your Helper application. The second parameter is a BOOL indicating whether the Helper should launch at login or not.

The helper app is required because SMLoginItemSetEnabled() only works with paths inside of the app’s Contents/Library/LoginItems folder.

Tim Schröder:

Consider further that you have successfully implemented such a feature and shipped your application, but now want to update your application to not run in a sandbox anymore. Sounds like a strange turn of things, but this may happen, e.g., if you designed an application to be distributed in the Mac App Store (and shipped it), but now there are compelling reasons to remove the sandbox functionality and to switch to direct distribution outside the Mac App Store.

It is then sensible to provide launch at login functionality no longer via SMLoginItemSetEnabled (and a helper app), but via a shared file list as provided by the Launch Services Framework, which has the distinctive advantage that your application will be visibly marked as launching at login in the System Preferences and that the user can edit this behaviour from the System Preferences (which is not the case with the launch at login functionality providing via SMLoginItemSetEnabled).

How iOS Has Changed

Khoi Vinh:

I don’t link to a lot of infographics here but I like this one, and I’ve always been fascinated by the incremental, barely noticed way some interfaces can change, even when we look at them all day long. This extensive graphic from 7dayshop.com presents a pretty comprehensive overview of how iOS has evolved.

Organ Banked

In response to my roundup about Apple’s software quality, a former Apple CoreOS person writes:

A lot of us felt we were being “organ banked”, and late in Lion, on the iDevice release cycle, we were pulled away from desktop work in order to do iPhone and iPad work, which was on a 3 month release cycle, instead of alternating desktop with non-desktop, which we had formerly done on a 6 months on/6 months off cycle (release one in fall/release the other in the spring).

The desktop vastly suffered because of this, and we felt that Lion and later were more or less “phone it in” releases for the desktop.

The comments from Apple insiders underscore that there are many factors that affect software quality. It is not simply a matter of dropping the yearly schedule or of deciding to do “another Snow Leopard.” The development schedule and cycles matter. It also matters who the engineers and managers are, how they are treated, whether they are shuffled between projects, etc.

There was a lot of resentment because when the initial iPhone came out, almost no one on the second floor of IL2 was allowed to look at the internal SDKs; even after the SDKs were finally released (a lot of Apple engineers by that point were on the “iPhone Dev Team”, and compiling their own apps for jailbroken phones, providing compiler and assembler fixed, and so on).

Then we had to wait 6 months after they started external classes before we were allowed on the platform, or in the classes. We all suspected that that was because there was incredible demand for iPhone programmers, and we’d get hired away from working on boring old crap like Finder and Mail and AddressBook, because Apple couldn’t hire people willing to work on boring crap any more.

This reminds me of three things:

Wednesday, January 21, 2015

MacKeeper

Peter Cohen:

But the real problems with MacKeeper that I can see is that it provides questionable value to most users, can destabilize an otherwise stable Mac, and embeds itself so thoroughly into the operating system that removing it is an uncomfortable and weird process.

Tuesday, January 20, 2015

WKWebView, Sandboxing, and Searching

Brent Simmons:

But the new replacement for WebView — WKWebView — doesn’t have this bug. Which is great. Let’s adopt the new thing! I’m all in. Love new things.

[…]

I did some research, and I learned that WKWebView won’t show local content — that is, files that are loaded from the app’s bundle. Files from the app bundle ought to be a-okay, ought not be a sandbox violation, but apparently they are.

[…]

In an ideal world, WKWebView would work with files from the app bundle, and, as a replacement for WebView, it would have the same functionality as WebView (a searchFor or equivalent method). Anything else means running as fast as I can while I slip backwards.

Update (2015-01-21): Chromium (via Martin Schurrer):

Unfortunately, despite the advantages of WKWebView, it has some significant technical limitations that UIWebView does not, which means we can’t simply drop it in as a replacement.

Update (2015-01-24): Dan Fabulich:

There is a workaround, demonstrated by shazron here https://github.com/shazron/WKWebViewFIleUrlTest to copy files into /tmp and load them from there.

Backing Up Discontinued Apps

Electronic Arts (via John Gordon):

EA is removing several of its older titles from the App Store, but if you already own these games, you will still be able to play them without interruption.

As always, we encourage our players to back up their app purchases in iCloud. If you uninstall the app without backing it up on iCloud or iTunes, you may not be able to redownload your game.

My understanding is that iCloud only backs up App Data. So if you want to restore an app that has been removed from the store you would need to have a backup in iTunes. And that app will probably never work with Family Sharing.

The Shape of the App Store

Charles Perry (tweet):

I expected a “hockey stick” curve that’s characteristic of power law models, but I didn’t expect one like this. The hockey stick breaks upwards at around position 870 on the U.S. Top Grossing list. With about 1.2 million apps in the App Store at the time the data was collected, that arguably puts 99.93% of apps in the “long tail” of the App Store. The “head” of the App Store, those 870 top grossing apps that make up 0.07% of the App Store population, collect over 40% of the App Store revenue that’s paid out.

Luckily, there’s a lot of money to be made in that long tail. At the top of the long tail, in position 871 on the U.S. Top Grossing list, an app still makes over $700 in revenue per day. That’s almost $260,000 per year. Even number 1,908 on the U.S. Top Grossing list makes over $100,000 per year.

His chart is based on the sales data from Marco Arment.

Filip Radelić:

Seems like a very optimistic approximation. I’ve seen apps around top 870 grossing with much, much less than $700/day.

Charles Perry (tweet):

I’ve gotten some feedback from readers asking how valid my extrapolated data is. Some have pointed out that I’m working with a limited data set from only one app that might not hold for all apps.

[…]

While the the exact revenue figures that I cited in The Shape of the App Store may be off little, it seems likely that they are at least in the right ballpark. They may even be somewhat conservative estimates if Manual’s revenue figures are to be believed.

JavaScriptCore

Nate Cook:

We can easily access any values we’ve created in our context using subscript notation on both JSContext and JSValue instances. JSContext requires a string subscript, while JSValue allows either string or integer subscripts for delving down into objects and arrays:

Swift doesn’t support the subscript notation, though.

With a JSValue that wraps a JavaScript function, we can call that function directly from our Objective-C/Swift code using Foundation types as parameters. Once again, JavaScriptCore handles the bridging without any trouble[…]

[…]

There are two main ways of giving a JSContext access to our native client code: blocks and the JSExport protocol.

[…]

Since blocks can capture references to variables and JSContexts maintain strong references to all their variables, some care needs to be taken to avoid strong reference cycles. Avoid capturing your JSContext or any JSValues inside a block. Instead, use [JSContext currentContext] to get the current context and pass any values you need as parameters.

Monday, January 19, 2015

Clearing the Icon Services Cache in Yosemite

Craig Hockenberry:

If you’re seeing any weird behavior with icons in Yosemite, the chances are good that the Icon Services cache is corrupted and needs to be reset. Here’s how you do it using the Terminal[…]

He’s right that Apple should have a built-in command for doing this. Icon cache problems have plagued Mac OS X for a long time, and the precise way to reset the cache keeps changing.

Kindling Projects

Ned Batchelder:

New programmers often need small projects to work on as they hone their skills. Exercises in courses are too small, and don’t leave much room for self-direction or extending to follow the interests of the student. “Real” projects, either in the open-source world or at work, tend to be overwhelming and come with real-world constraints that prevent experimentation and pure coding practice.

Kindling projects are meant to fill this gap: simple enough that a new learner can take them on, but with possibilities for extension and creativity. Large enough that there isn’t one right answer, but designed to be hacked on by a learner simply to flex their muscles.

Update (2015-01-20): Tim Schmitz:

Ned is mostly talking about new programmers, but this is quite similar to what I had in mind when I started my current app project. The idea was to get some experience working with Swift as well as a few other technologies that I haven't worked with extensively in the past. Even though I'm not new to programming, we're all relatively new to Swift.

Sunday, January 18, 2015

MacUser UK Closes

Dennis Publishing (via Charles Arthur):

Since its launch in 1985 MacUser has provided its readers with authoritative buying advice, world exclusive reviews, breaking news and practical features. Inspired by the late Felix Dennis’ purchase of an Apple Lisa in 1983, the magazine started life as a bi-monthly magazine but soon upped its frequency to fortnightly as readers and advertisers poured in. The magazine was launched in the USA in 1985 where similar success followed.

[…]

The decision to cease publication of MacUser was very tough and one that was not taken lightly. Unfortunately, due to challenging market conditions, the closure was unavoidable.

It’s a tough business.

Update (2015-01-20): There’s also a blog post (via John Gruber).

Matt Gemmell:

It was from MacUser that, variously and over the years, I developed an interest in typography, colour theory, video editing, and a host of other subjects. I’ve been a subscriber, a reader, and even a contributor, and the closing of the magazine is a great loss to the Mac community.

MMWormhole: Message Passing Between iOS Apps and Extensions

MMWormhole (via Marco Arment):

MMWormhole creates a bridge between an iOS extension and its containing application. The wormhole is meant to be used to pass data or commands back and forth between the two locations. Messages are archived to files which are written to the application’s shared App Group. The effect closely resembles interprocess communication between the app and the extension, though true interprocess communication does not exist between extensions and containing apps.

The wormhole also supports CFNotificationCenter Darwin Notifications in an effort to support realtime change notifications. When a message is passed to the wormhole, interested parties can listen and be notified of these changes on either side of the wormhole. The effect is nearly instant updates on either side when a message is sent through the wormhole.

See also: iOS IPC via NSFileCoordinator and NSFilePresenter.

How Amazon Tricks You Into Thinking It Always Has the Lowest Prices

Jason Del Rey (via Hacker News):

In one example, Boomerang observed Amazon testing price reductions on a $350 Samsung TV — one of the most popular TVs on Amazon — over the six months leading up to Black Friday. Then, on Black Friday, it dropped the price to $250, coming in well below competitors’ prices.

But when it comes to the HD cables that customers often buy with a new TV, Amazon actually pushed up the price by 33 percent ahead of the holidays.

[…]

“Amazon may not actually be the lowest-priced seller of a particular product in any given season,” the report reads, “but its consistently low prices on the highest-viewed and best-selling items drive a perception among consumers that Amazon has the best prices overall — even better than Walmart.”

Yosemite’s FileVault 2 Pre-boot Recovery Options

Rich Trouton (tweet):

One of the changes that Apple has introduced with Yosemite is a more straightforward way to recover from login problems at the FileVault 2 pre-boot login screen.

[…]

In the Reset Password wizard, there are currently three options available.

  1. I forgot my password
  2. My password doesn’t work when logging in
  3. My keyboard isn’t working when typing my password to login

Saturday, January 17, 2015

Vintage Mac About Boxes

Riccardo Mori:

I started going through them one by one (the applications, at least; the games are more than 200!), and invoking their About boxes to find out exactly which version they were. I found some very old versions of popular applications and — equally interesting — there were also not-so-old versions of popular applications but in French and even German. I thought this exploration was worth capturing, so I took a few screenshots. Here’s a selection of the most interesting findings.

100 Years of Computer Science

Chris Ford (via Ole Begemann):

I came to appreciate academic papers relatively late. While a student, I can only specifically remember reading two papers, one of which (by Claude Shannon) appears below. As a professional programmer without a strong theoretical background, papers seemed difficult and unapproachable, and it took me a long time to realise what I’d been missing.

Some colleagues, responding to my new-found enthusiasm, asked me for recommendations on where to start. Inspired by similar lists by Michaels Feathers and Fogus, I’ve compiled a timeline of papers that (for me) represent something of the spirit of the development of computer science over the past 100 years.

He chose one paper from each decade.

Mergeable Persistent Data Structures

Benjamin Farinier et. al. (PDF) (via Adrian Colyer):

Distributed version-control systems (DVCSs) are widely used to manage the source code of software projects. These systems are at the core of any workflows to produce and maintain large software stacks that involve many branches of development and maturity. DVCSs are used to keep track of change provenance and help to relate newly discovered bugs in the software to the context of the modification of the source-code which caused it.

We wish to see the same kind of workflow applied to data as well as source code. What if you could version-control a (mutable) persistent data structure, inspect its history, clone a remote state and revert it to a previous state? We find that using the existing tools around source-code DVCS and applying them to application data results in significant benefits to developing distributed applications. Instead of structuring our system like a conventional database, we instead provide the functionality as a library that can be linked and customised directly by the application logic.

Real World Swift

Chris Surowiec (via iOS Dev Weekly):

Our biggest gripe – and source of frustration – with Swift is probably not the language itself, but the tooling around it. Xcode (Apple’s Objective-C and Swift IDE) does not yet feel solid with Swift code. During development of our app, the IDE would often slow down noticeably or crash. There was no (or very slow) code completion most of the time, basically no debugger, unstable and unreliable syntax highlighting, a slow text editor (once the project reached a certain size), and no refactoring tools.

Additionally, compiler errors are often incomprehensible and there are still quite a few compiler bugs and missing features (e.g. type inference sometimes goes awry).

[…]

The number one crash group (at ~30% of all crashes) comes from an external Objective-C library. In fact, four of the top five crash groups come from Objective-C land (the fifth being a failing assert, which we leave enabled in production builds).

Also of note, the seventh most common crash comes from the previously mentioned Apple-provided Objective-C function that will sometimes @throw exceptions without being documented as such (-[AVAssetWriterInputHelper markAsFinished]).

[…]

You can certainly tell that some of Xcode’s features become slower and slower as your project grows, and we are not the only ones noticing. Iteration time (the time it takes after making a code change, hitting CMD+R, and having your app run in the simulator) is also worse than in Objective-C. A quick test shows that adding a single line brings the wait up to 14 seconds, and this varies greatly depending on what you do. Making a similar change in our Objective-C based app takes about two to three seconds.

iOS App Sales Data

Dan Gray shares the sales numbers for the Monument Valley (App Store) game.

Marco Arment (tweet) shares the numbers for his Overcast (App Store) podcast client.

William Wilkinson (tweet) shares the numbers for his Manual (App Store) camera app.

Skip the FFI: Embedding Clang for C Interoperability

Jordan Rose:

Most languages that aren’t a superset of C provide a Foreign Function Interface (FFI) that allows one to interface with existing C libraries. FFIs are often an afterthought, requiring manual or source-to-source translation from C header files to a subset of the target language, resulting in complicated build processes, frequent manual tweaking, and numerous implementation challenges.

This talk will discuss an alternative approach that embeds Clang into an LLVM-based compiler front end to provide C compatibility without the traditional FFI. Embedding Clang provides seamless access to C APIs, moving the translation of APIs from external tools into the compiler itself. Moreover, one can leverage Clang’s deep knowledge of C record layout and calling conventions to simplify the C interface and make both bring up and porting of a new compiler front end simpler.

The Stunning Scale of AWS

Todd Hoff (via Steven Sinofsky, comments):

All 14 other cloud providers combined have 1/5th the aggregate capacity of AWS (estimate by Gartner in 2013)

[…]

The cost of networking is escalating relative the cost of all other equipment. It’s anti-Moore’s law. All other gear is going down in cost, networking is getting relatively more expensive over time. Relative monthly costs: servers: 57%; networking equipment: 8%; power distribution and cooling: 18%; power: 13%; other: 4%.

[…]

Amazon’s solution 5 years ago was data driven and radical: they built to their own networking designs. Special routers were built. A team was hired to build the protocol stack all the way to the top. And they deployed all this themselves in their network. All services worldwide run on this gear. […] source of the improvement was simplicity. The problem AWS was trying to solve was simpler than the problem enterprise gear tries to solve. Enterprise gear must adhere to a lot of complicated specs that go unused and only make the system more fragile. By implementing just the functionality that was required meant a much simpler system which lead to higher availability.

Something Slightly Less Terrible

Loren Brichter:

It’s not like a boat with a couple of holes that we can patch; it’s more like trying to sail across an ocean on a pile of accrued garbage. Sure, some of the stuff floats, and it keeps some other stuff from sinking. A better question might be: which parts are good? And you can only answer that if you look at a thing in isolation. Like, I could say that Rust is good. But even that enshrines the Von Neumann philosophy, and so you can crawl your way down the stack questioning everything, which isn’t practical.

[…]

Personally, I’m tired of the trivial app stuff, and the App Store isn’t conducive to anything more interesting. I think the next big thing in software will happen outside of it.

Video and iOS Rotation Lock

Tim Schmitz:

In fact, I leave auto-rotation enabled for one simple reason: video. Most video fits far better in landscape orientation than in portrait. The iPhone's screen is perfectly shaped for wide-aspect video in landscape. Unfortunately for me, iOS won't rotate video into landscape orientation unless it can rotate the whole OS into landscape. Put another way, if I use rotation lock to keep the phone in portrait orientation, that applies to video as well. That means video gets letterboxed into a postage stamp-sized area in the center of my screen.

I wish it would show video in landscape and everything else in portrait.

Update (2015-01-25): Garrett Murray:

There are, however, two cases in which I want the option to use landscape mode: playing games and watching video. Tim’s suggestion of video ignoring rotation lock would be perfect (applied to games as well, obviously). If I had my way, I’d remove landscape from iPhone in iOS entirely but for these two scenarios.

Wednesday, January 14, 2015

Swiftifying Apple’s Framework APIs

Mattt Thompson:

And yet, after just a few months of working with Swift, Cocoa has begun to lose its luster. We all saw Swift as the beginning of the end for Objective-C, but Cocoa? (It wouldn’t be the first time an Apple standard library would be made obsolete. Remember Carbon?)

Andy Matuschak:

I don’t actually have insider knowledge here, so this is just speculation, but I think it will be a long process. At least when I was there, the teams spent the majority of their time not maintaining and improving frameworks, but really supporting market features like new screen sizes or support for new hardware. That’s what takes most of the time. So it will take a conscious decision to do anything non-trivial, and I don’t see that forthcoming.

Cocoa Thread Utilities

Todd Ditchendorf’s Cocoa Thread Utilities offers semaphores, bounded buffers, synchronous channels, thresholds, and triggers.

Switching From Core Data to Realm

Tim Oliver (tweet):

Tim Oliver, creator of the iComics app, gave a talk featuring Realm in his project at the Perth iOS Meetup. His talk covered gave a quick background of his transition to and experiences using Realm in place of Core Data, a switch he made in just one evening.

[…]

When I was working on iComics, I’d have problems when a background thread would import a comic, tell the main thread the comic imported, then send an object with entirely empty fields. When I tested installing a new version of the app over an older version, I found that Core Data’s auto-migration was corrupting half the database and making the app very unstable. A manual Core Data migration would have required a ridiculous amount of code, and I decided to switch to Realm.