Archive for February 1, 2015

Sunday, February 1, 2015

Phantom Types and Typed Notification Observers

objc.io:

Using these types, we can create two more wrappers, but this time around NSFileHandle’s initializers. We’ll use the Read and Write types, even though the FileHandle doesn’t contain any values of that type. That’s why the A parameter is called a phantom type. The types are just there to track permissions.

[…]

Trying to call this function on a file-handle that’s open for writing will not even compile. You can use these techniques for important parts of your own code as well, if you have areas where you want the compiler to check errors for you, rather than having the code fail at runtime.

objc.io:

Finally, we can create our observer object. Creating an instance of this object adds an observer to NSNotificationCenter, and when it deallocs, it removes itself from the notification center. This allows us to store it as a property on an object, and once the property gets set to nil (e.g. when the object deallocs), it automatically removes itself from the notification center.

Then they use phantom types to make sure that a given notification is always posted with the proper type of user info object.

The IOU of iOS

Chris Ashworth:

If some app developers “earn more than Hollywood stars”, and the median developer income is better than abject poverty… that doesn’t tell us that the App industry is healthy so much as at least slightly less insane than working as an actor. Which, and I say this as an actor, is true of, well, basically any other job. So, not much to learn there.

[…]

The sense I sometimes get with iOS is of work done in exchange for a vague IOU. A belief in the obvious technical and design merits of the platform, an acknowledgement of the unprecedented rates of adoption for these devices, and perhaps an excitement watching the stars strike gold. A culture thick with the pervasive mantra “mobile first”, which might make all the sense in the world to one kind of business endeavor, but may make no sense at all for other kinds of toolmakers.

Apple is not, I would say, directly (or consciously) responsible for promising something that iOS can’t deliver. But neither are they entirely neutral. They design the mechanics of the App Store. They design and construct how apps are discovered.

[…]

The 30% cut Apple takes really is huge. It also, I think, encourages us to build apps that are free. And if the apps are free, they’re in service to something else that isn’t free. Some software-as-a-service, or a product sold through another channel which can be made more attractive with a mobile extension. This gentle pressure to push the actual value outside of iOS strikes me as problematic, long-term.

Swift & the Objective-C Runtime

Nate Cook:

Unfortunately, a load class method implemented in Swift is never called by the runtime, rendering that recommendation an impossibility. Instead, we’re left to pick among second-choice options:

  • Implement method swizzling in initialize
    This can be done safely, so long as you check the type at execution time and wrap the swizzling in dispatch_once (which you should be doing anyway).

  • Implement method swizzling in the app delegate

Dynamic Casting in Swift

Samuel E. Giddins:

We can even define some syntactic sugar on top of this type verification:

func id<U>(object: AnyObject) -> U? {
  if let typed = object as? U {
    return typed
  }
  return nil
}

[…]

OK, that last example might not look like a huge improvement, but coupled with Swift’s powerful type inference, you can 'magically’ type objects at runtime with a single function call.

You have to call the id() function, but depending on the context Swift may be able to infer the types.

1Password 5.2 for iOS and 5.1 for Mac

Agile Bits:

For our Pro feature owners, let’s start with a new One-Time Password tool. This helps you sign into a growing number of services (like Amazon and Tumblr) that support a secondary, randomized password for that extra… je ne sais quoi. You can learn more about One-Time Passwords at TwoFactorAuth.org.

It’s nice to not have to rely on Google Authenticator for two-factor authentication. Plus, 1Password’s data is easier to back up and sync. Google Authenticator has the advantage of larger digits that (in recent versions) are separated into two groups with a hyphen. Given that my QR code images are already stored in 1Password, you would think there would be a way to import them directly, but it was easy enough to aim the phone’s camera at 1Password on my Mac.

Agile Bits:

In short, we completely overhauled how you manage sync for your primary and secondary vaults to save you time. In Preferences > Sync, you can now view all your vaults and how they sync, and change sync methods with a click.

This is much nicer, although you still cannot edit the color or icon for a secondary vault after creating it.

Weakness

Edge Cases discusses weak references and how entries in Andrew Pontious’s hash table don’t get cleared away promptly. Surprisingly, Apple’s doesn’t do better.

Categorical

Soroush Khanlou:

-[NSString containsString:] was added in iOS 8. If you’re writing a standard library, this seems like one of the most crucial components for string handling. And yet, it’s been conspicuously absent since the early ’90s, when NSString was created.

[…]

So given these myriad reasons why categories aren’t good enough, why will Apple not implement these methods?

[…]

Other vendors have proven that it’s possible to do this well. Ruby, for example, takes it to the other extreme: their Integer objects respond to methods like #odd?, #even? and even #gcd. Providing those methods in the standard library yields more readable code and it gives the vendor the opportunity to tweak and optimize them at later date, knowing that anyone who needs them will benefit from their optimizations.

[…]

In the same way that base types like Swift’s Optional or JavaScript ES6’s Promises must be built-in for proper adoption, these simple methods need to be available to all developers. Apple’s proclivity towards leaving holes in their API forces developers into a bind. We must either write inexpressive, hard-to-read code, do needless work opening these classes back up, or leave a trail of dependencies in our wake.

YouTube Now Defaults to HTML5 Video

Richard Leider (via John Gruber):

Four years ago, we wrote about YouTube’s early support for the HTML5 <video> tag and how it performed compared to Flash. At the time, there were limitations that held it back from becoming our preferred platform for video delivery. Most critically, HTML5 lacked support for Adaptive Bitrate (ABR) that lets us show you more videos with less buffering.

Over the last four years, we’ve worked with browser vendors and the broader community to close those gaps, and now, YouTube uses HTML5 <video> by default in Chrome, IE 11, Safari 8 and in beta versions of Firefox.

Web video is getting better, but the situation remains difficult with older Macs. My grandmother’s Mac mini can’t run anything later than Snow Leopard. She is constantly running into problems with YouTube because her Flash Player is too old. It seems unable to update itself automatically. I wanted to set her up with Chrome, which has its own Flash and its own auto-updater. It works on 10.6 but only if you have a 64-bit Mac. Meanwhile, YouTube wants Safari 8, but Snow Leopard can only run Safari 5.

Who Else Kinda Misses Their Zip Disks?

Christopher Phin:

A little over 20 years ago, however, when Iomega introduced the original 100MB Zip disk, that was staggeringly huge for a removable disk. The wildly more common 3.5-inch floppies held 1.4MB. For context, the entry-level PowerBook 150, introduced in the same year, had a 120MB hard disk, and the base configurations of even 1994’s server Macs came with hard disks that were only five times the capacity of the Zip disk.

The humble Zip disk, then, was a kind of de facto successor to the ubiquitous high-density 3.5-inch floppy. You had to buy a special drive to mount it in, because although they had about the same footprint as a regular floppy disk, they were much thicker. In fact, Zip disks had a lovely chunky, seemingly hugely robust quality compared to normal floppies.

As I recall, the novelty wasn’t that the Zip disk was huge in capacity. In that respect, it was similar to the SyQuest and Bernoulli removable disks of the day. What was special was that Zip disks were physically smaller and much cheaper. And, in spite of the “click of death,” I recall them being more reliable than their 88 MB SyQuest predecessors and their 1 GB Jaz successors.

Some Notes on Rust, the Language

John Nagle:

Despite the claims in the Rust pre-alpha announcement of language definition stability, the language changes enough every week or so to break existing programs. This is a classic Mozilla problem; that organization has a track record of deprecating old features in Firefox before the replacement new feature works properly.

[…]

Rust is going to be a very important language, because it solves the three big problems of C/C++ that causes crashes and buffer overflows. The three big problems in C/C++ memory management are “How big is it?”, “Who owns and deletes it?”, and “Who locks it?”. C/C++ deals with none of those problems effectively. Rust deals with all of them, without introducing garbage collection or extensive run-time processing. This is a significant advance.

Protocols and Swift

Ash Furrow:

Here’s the problem I ran into: in a pure Swift environment, I want to have optional methods in my protocol so that objects that conform to it may opt-in to certain functi onality. It turns out that this is really really hard.

[…]

I’m not saying that this is necessarily how I would actually write things – it’s only supposed to show you how dividing areas of concern into separate protocols makes things a lot more clear.

[…]

Sure, you’ll probably have only one object that conforms to all the protocols you need (and be honest – it’s probably a view controller, isn’t it?). But the power of this technique is not that we can divide the various data sources into different objects. Instead, the advantage is that we don’t have additional semantic coupling between functions in the protocol. Of course canMoveRowAtIndexPath can only be called if moveRowAtIndexPath is also implemented – they’re in the same protocol.

Update (2015-02-02): David Owens II:

It’s just another way of thinking about the problem. Swift seems to be a language that values immutability and composition over mutability and if we start to think about solving problems that way, I think we end up with more solutions like I presented where it’s really just about how we manipulate the data in composable ways.