• CocoaPods Spec Repo

    If you’ve tried to run pod install in the last day or so, you probably found yourself stuck.

    Updating spec repo `master`

    Yeah. Yikes.

    As discussed by GitHub’s @mhagger, the CocoaPods/Specs repository (where all the podspecs are stored) experiences extremely high volume, due in part to shallow initial checkouts of the repository. He leaves a helpful tip to convert the specs repo to a deep checkout.

    I tried it, it makes things fast.

    cd ~/.cocoapods/repos/master/Specs
    git fetch --depth=2147483647

    This will take a few minutes to run, but pod install, pod update, etc are all much faster now.

  • Freedom 251

    This is definitely the cheapest smartphone I’ve ever seen, at 251 Rs ($3.67 at the time of writing).

    I like the tradeoffs they’ve made to fit the price point. A 3MP camera and 8GB of built-in storage is perfectly acceptable when merely having a cellular data connection is the big needle mover. We’ve built up a convenient narrative in calling the iPhone and high-end Android devices ‘premium’ while largely ignoring that having any data connection on the go is still a premium experience for much of the world.

    From their mission:

    Empower citizens, even in the remotest rural and semi-urban centres of India, with the latest in digital technology at incredible affordable prices and cascade knowledge, news and current issues so that all experience the confidence of inclusive growth and equal opportunity - In short, innovative solutions for a Brighter tomorrow.

    Awesome.

    On sale 7:30PM EST tonight. Don’t know if orders will be available outside of India but I’d love to order one and support this effort. freedom251.com

  • CoreMedia Time Division

    I’ve got a pretty happy relationship with AVFoundation, but the CoreMedia API’s can sometimes be inscrutable. Today, it’s time division. Given the existence of CMTimeMultiply, one might expect ‘CMTimeDivide’. Instead, we find CMTimeMultiplyByRatio

    let time = CMTimeMakeWithSeconds(43804, 600)
    
    let divided = CMTimeMultiplyByRatio(time, 1, 4)
    
    (lldb) print divided
    	 (CMTime) $R0 = {
    	  value = 43804
    	  timescale = 2400
    	  flags = (rawValue = 1)
    	  epoch = 0
    	}

    Notice that CoreMedia works smartly underneath the hood. Rather than divide the value, it simply scales the timescale, keeping the value evenly divisible by the timescale. What happens if we use CMTimeMultiplyByFloat64?

    let dividedByFloat = CMTimeMultiplyByFloat64(time, 0.25)
    (lldb) print dividedByFloat
    (CMTime) $R0 = {
      value = 18251666667
      timescale = 1000000000
      flags = (rawValue = 3)
      epoch = 0
    }

    We can see that instead of scaling the timescale, the value and timescale have been expanded, as well as a new flag added.

    // Inspect the flags from using CMTimeMultiplyByRatio
    (lldb) print divided.flags.contains(.Valid)
    (Bool) $R1 = true
    (lldb) print divided.flags.contains(.HasBeenRounded)
    (Bool) $R2 = false
    
    // Inspect the flags from using CMTimeMultiplyByFloat64
    (lldb) print dividedByFloat.flags.contains(.Valid)
    (Bool) $R6 = true
    (lldb) print dividedByFloat.flags.contains(.HasBeenRounded)
    (Bool) $R7 = true

    This tells us that CoreMedia has done some rounding in the CMTimeMultiplyByFloat64 calculation, while CMTimeMultiplyByRatio remained exact. The documentation sheds some more light on the exact behavior:

    The exact rational value will be preserved, if possible without overflow. If an overflow would occur, a new timescale will be chosen so as to minimize the rounding error. Default rounding will be applied when converting the result to this timescale. If the result value still overflows when timescale == 1, then the result will be either positive or negative infinity, depending on the direction of the overflow.

  • Introducing Yayy

    I’m very excited to announce Yayy, available today on Apple TV. A collaboration with Eric Robinson, we’ve created Yayy to be the absolute best way to find and enjoy gifs on a big screen. Your blank TV screen just got 1000% more fun during parties.

    When the new Apple TV was announced in September, a flurry of enthusiasm and ideas came to me in a way that I haven’t felt since the original iPhone announcement. The barriers have finally started to fall on a medium that has traditionally been driven by gatekeepers with questionable business practices and no interest in quality. We’re just scratching the surface of what’s possible.

  • Invalid UIUserNotificationSettings

    I was testing push notifications with custom categories recently and noticed that they had stopped coming through. After checking out the code that registers these categories I saw that in one case a UIMutableUserNotificationCategory was being created correctly, while one of it’s corresponding UIMutableUserNotificationAction objects was instead being passed to the notification settings. This is invalid, and apparently gets cached in between runs of the app (even though you’re reacreating the categories at runtime).

    The trick, which I stumbled on after a few minutes of head scratching, is that you must delete and reinstall the app in order for things to start working again. But why should I be surprised? Programming for push notifications is crazy.