Rethinking Apple Music

When I launch an app like Apple Music, I’ve got just a handful of simple questions in mind:

Apple Music only tries to answer the last of these questions (and it answers it poorly). The other four questions aren’t answered at all.

It’s often a mistake to think that one’s anecdotal experience is representative of people in general, but in this case I believe my music habits aren’t far off from most people’s. Music appreciation is a learned skill. We learn how to enjoy music by imitating our friends and heroes. Whether it’s thumbing through the sun visor CD case of that cool friend from high school, or flipping through your dad’s box of old vinyl, we try on the tastes of other people to see what fits. It’s how our taste grows, embraces new favorites.

The social nature of taste, and of musical taste in particular, is so fundamental that it should be the organizing principle of Apple Music. Here’s how I think they should do it:

  1. Five New Tabs - Reorganize the top level of the app into five tabs that answer the fundamental questions: Keep Listening, Friends, Everyone, New Releases, and For You.
  2. Bye, Bye, iPod - Break out all the legacy iPod features into another app.
  3. Consistent Visual Grammar - Create a consistent visual grammar that allows albums, playlists, and radio stations to exist as siblings on any screen.
  4. Let Me Choose My Heroes - Make it easy for me to browse the music habits of my heroes, whether they’re celebrities or the cool kids down the street.

I. Five New Tabs

Reorganizing the app into the following tabs will make it map closely to the common modes in which we look for music.

Search

While not a tab per-se, all five tabs need to have a persistent, easily-accessible search button. Searching is the one activity (besides playback controls) that needs to be instantly available regardless of the current context.

II. Bye, Bye, iPod

All the vestigial traits from the iPod need to be lanced and sewn together in some other app, buried on a second home screen. Perhaps it could be served from the App Store only if you really need it, like iBooks used to be. The days of owning music are numbered. Even a once-fundamental concept like a collection is no longer relevant in a world where (theoretically) all music is available to all users at the touch of a button. Removing legacy iPod features would eliminate most of the egregious forms of complexity from Apple Music, such as trying to figure out why an album isn’t showing up in the search results.

III. Consistent Visual Grammar

Since the five tabs described above are organized around answering the fundamental questions, this presupposes that each tab is capable of presenting albums, playlists, stations, or some combination of the three. In order to do this without creating confusion, a system should be developed that makes it easy to tell at a glance whether an item in a list is an album or a playlist or a station. Whether it’s by changes in shape or texture, or by filters that hone the the visible results, or some other form of grouping, the precise grammar doesn’t matter so much as the need for consistency. Once I learn how to distinguish the three kinds of items, I should be able to apply that knowledge no matter what screen I’m using. In the current Apple Music app, the presentation of these items varies dramatically depending on which screen you’re on. This inconsistency makes the app difficult to understand and distracts from the browsing experience.

IV. Let Me Choose My Heroes

No algorithm will ever generate as beloved a surprise as snooping through the music habits of one of my heroes. Back when Rdio was alive, whether it was a “celebrity” like the members of Y La Bamba, or a cool Internet friend like Neven Mrgan, my most satisfying surprise musical finds came from browsing the tastes of people I admire. Algorithms have their place (when I’m in the mood for something familiar), but they shouldn’t be used exclusively. Nor should Apple’s hubris be allowed to go on unchecked, filling my Apple Music app with Carly Simon playlists and Jumpman Jumpan Jumpan Jumpan remixes. I want to listen to what my heroes are listening to, and they’re not listening to what Cupertino listens to.

|  4 May 2016




A Very Narrow Usage of Storyboards

Lately I’ve been struggling to balance the pros and cons of various view controller initialization techniques. There are three, none of which are perfect:

Lately, the projects I’ve been working on have had pretty heavy AutoLayout requirements. As such, it’s been easiest to build the user interface logic using a Storyboard. But the Storyboard approach makes it really hard to pass in dependencies in a simple, reliable fashion.

Until Apple provides a better solution, my current strategy is to provide a static factory method that takes as arguments all the dependencies that need to be passed in:

static func newFromStoryboard(foo: FooDependency, bar: BarDependency) -> MyViewController

In addition, I make the relevant instance variables private, so that they can only be set from inside the file:

private var foo: FooDependency!
private var bar: BarDependency!

The factory method instantiates the view controller from the correct storyboard, and then sets all the dependencies. I only use one view controller per storyboard, and never use segues.

This is not the most elegant approach I can imagine, but I believe it’s the least inelegant approach made possible within the current state of the UIKit framework and Swift.

|  27 Apr 2016




Don DeLillo on Chickenshit White UI Design

We ran into Murray Jay Siskind at the supermarket. His basket held generic food and drink, nonbrand items in plain white packages with simple labeling. There was a white can labeled CANNED PEACHES. There was a white package of backon without a plastic window for viewing a representative slice. A jar of roasted nuts had a white wrapper bearing the words IRREGULAR PEANUTS. Murray kept nodding to Babette as I introduced them.

“This is the new austerity,” he said. “Flavorless packaging. It appeals to me. I feel I’m not only saving money but contributing to some kind of spiritual consensus. It’s like World War III. Everything is white. They’ll take our bright colors away and use them in the war effort.”

From White Noise.

|  26 Apr 2016




I admit I never understood what Manton found appealing about microblog posts until today, a week...

I admit I never understood what Manton found appealing about microblog posts until today, a week into my Giving Up On Twitter experiment, inspired by Seth. Seth’s feelings about Twitter caught me off guard. I think I’ve been having a similar experience. So I deleted all but Tweetbot, disabled all but the minimal socially-acceptable push notifications, and moved it to a third home screen folder.

|  25 Mar 2016




Imagining a First-Party Swift KVO Replacement

My last post got me thinking: if Apple were to add a KVO-like service to Swift, what would it look like? I wish I understood more about how programming languages are created, and how compilers work. What follows isn’t really a serious proposal, but just a sketch of what I would personally want to use as a practicing software developer.

What if every Swift class received an implicit, protected member with a reserved name like observables which provided a means to register closures as observers for changed values? An example usage might look like this:

let tweet = Tweet(text: “Hi.”)
tweet.observables.isLiked.addObserver { (oldValue, newValue) -> Void in
    // this is otherwise just a standard closure, with identical
    // memory management rules and variable scope semantics.
    print(“Value changed.”)
}
tweet.isLiked = true // Console would log “Value changed.”

The observables property would be implied, just like self. It would be an instance of some ad-hoc generated Swift class created by the compiler at compile time. For every observable property of the owning class, this observables class will have a corresponding observable property. So if you created a class like this:

class Tweet {
    var isLiked: Bool = false
    let text: String
    
    init(text: String) {
        self.text = text
    }
}

The Swift compiler would generate a class like this and assign it to the observables property for Tweet:

class Tweet_SwiftObservables {
    let isLiked = Observable<Bool>()
}

The Tweet_SwiftObservables class name would be auto-generated based on the class name of the target class. Notice that only the isLiked property is carried over, since the text property of Tweet is a let, not a var.

The isLiked member of Tweet_SwiftObservables is an instance of a generic Observable<T> class, whose implementation would be something like the following (though, of course, more nuanced):

class Observable<T> {
    typealias Observer = (oldValue: T?, newValue: T?) -> Void
    private var observers = [UInt: Observer]()
    
    func addObserver(observer: Observer) -> Uint {
        let token: Uint = 0 // generate some unique token
        self.observers[token] = observer
        return token
    }
    
    func removeObserverForToken(token: Uint) {
        self.observers[token] = nil
    }
}

The money shot is the addObserver() method. This method accepts a single Observer argument, which is just a simple closure. It would follow all the existing rules of memory management and variable scope as any other closure. addObserver() returns a unsigned integer token that can be used to remove the observer at a later time.

What I like about my idea is:

|  1 Jan 2016