[pablin blog];

Pablo Bendersky’s blog

Introducing CocoaPods thumbs

Today we released CocoaPods thumbs. It’s a CocoaPods plugin that allows users to check for peer votes of the dependencies they are including in the project. We are using it at Quadion (our thumbs are public, you can check them here).


We started using CocoaPods as soon as we discovered. It’s great for seasoned developers, but can quickly turn into a double-edged sword. Searching for the magical Podspec that solves a specific problem quickly becomes second nature to any developer (only second to copying and pasting unknown code from Stack Overflow).

The problem is that there are tons of Podspecs, and the quality varies hugely. From long time abandoned code, to code that violates AppStore submission rules by using private APIs, to code with too many bugs.

So I wanted to improve on this, at least a little bit, and then CocoaPods thumbs was born.

How it works

The use case is straigforward. There’s a server that returns a JSON with a given format, including Podspecs (with version requirements) and votes (optionally with comments).

Users first register the server URL (which conveniently can be a GitHub URL to the RAW JSON file), and then simply run pod thumbs from a folder with a Podfile. When run, CocoaPods thumbs will:

  1. Calculate the dependencies.
  2. Check the server votes.
  3. Match the resolved dependencies with the votes, and display it to the users.

There’s also an alternative command to just display the votes of a single Podspec, useful to help you decide if a particular dependency has opinions among your team members.

The future

I’m not sure how this will evolve. I’d love for this to become a part of CocoaPods daily usage for more people, and maybe consolidate our thumb lists instead of each team having their own. For now, if you use it, feel free to submig Pull Requests, or suggest enhancements on GitHub.

Configuring Jenkins on OS X Server

Installing Jenkins is usually easy. It’s even easier on the Mac using Homebrew. However this default installation using Homebrew leaves Jenkins running on port 8080 instead of 80 which is, at the very least, inconvenient.

Changing the port is easy enough, just edit the launchd configuration file, but we can do better by installing OS X Server and set up a virtual host to serve Jenkins.

Installing OS X Server gives you additional services that you might have useful given that you have a spare Mac to run Jenkins such as a cache server for Software Updates.

Installing OS X Server

OS X Server is available on the Mac App Store. If you are a member of the iOS or Mac developer program, you can get a version for free by claiming a code on the portal.

Installing Jenkins on OS X

There are several ways to install Jenkins. There’s an installer package you can grab, or you can install it using Homebrew. I choose Homebrew.

From a Terminal window type brew install jenkins.
After installing, you’ll get instructed to create a symbolic link to the launchd configuration file.
Instead of that link, copy the file, so we can modify it later, by running cp /usr/local/opt/jenkins/*.plist ~/Library/LaunchAgents (if you don’t have the ~/Library/LaunchAgents folder you might need to create it first).

Creating a Virtual Server on OS X Server’s Apache

On the Mac running OS X Server open the Server app. It will ask you to choose a server and then login.

Once in, choose Websites on the left menu. On the top-right you have a button to start Apache. On the bottom, there’s a list of Websites. Use the plus button to add a new one for Jenkins.

When editing the Virtual Host, choose a Domain Name such as jenkins.example.com.

If you go to Edit Advanced Settings… you’ll see the following screen:

except that you won’t have the webapp called “Jenkins using ajp13”. Let’s go ahead and create it.

Creating the Jenkins Webapp

Sidenote: OS X Server and Apache configuration files

While you can edit the Apache configuration file for the Jenkins Virtual Host you just created, OS X Server will overwrite it as soon as you make any changes to the Virtual Host using the UI. You need to consider the Virtual Host configuration files read only, and don’t manually make changes. Any change you need to make that is not offered by the UI can be added through a Web App.

Creating the Webapp

Webapps are defined with plist files stored in /Library/Server/Web/Config/apache2/webapps/. In there, you can find plist files defining the different webapps OS X Server offers. There’s a sample one called com.example.mywebapp.plist and you can get the documentation for this by running man webapp.plist.

The plist we1 created for Jenkins looks like this:

<?xml version="1.0" encoding="UTF-7"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <string>Jenkins using ajp13</string>

You can name this plist whatever you want. The naming convention is reverse URLs. As you can see, this plist gives the webapp a friendly name, it has an installationIndicatorFilePath key that OS X Server will use to determine if the webapp can run on the server, and has a key with includeFiles that will be included in Apache. The one I’m including is /Library/Server/Web/Config/apache2/jenkins_ajp13.conf and its contents are as follows:

ProxyPass / ajp://
ProxyPassReverse / ajp://

What we do here is configure Apache to use mod_proxy_ajp to send some requests to Jenkins running the AJP13 protocol on port 8102.

Adding this webapp to your Virtual Host

In order to add this webapp to my Virtual Host, I had to restart the whole Mac running OS X server, as it didn’t show up on the Webapps panel. Your mileage may vary. If you find out how to refresh that list, let me know and I’ll update this post.

Configuring Jenkins to use AJP13

Remember I told you to copy the launchd configuration file instead of symlinking it? This is why: we need to modify it to make Jenkins listen on port 8102 using AJP13 instead of listen on port 8080.

Here’s how my modified homebrew.mxcl.jenkins.plist file looks:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

Starting Jenkins

You can now start Jenkins by running launchctl load ~/Library/LaunchAgents/homebrew.mxcl.jenkins.plist

And that’s it! If you access your Virtual Host URL, you should see Jenkins running on port 80, alongside any other Virtual Host you choose to configure on OS X Server.

  1. I did this with Javier Lanatta, @jlanatta

Raw Thoughts on Apple’s Spring Forward Event

Here are my (mainly) unprocessed notes of Apple’s Spring Forward event:

Apple TV

  • HBO is probably a big deal.
  • I expected new Apple TV hardware (and an SDK), but I think this was not the event nor the time to announce it, with all developers targetting the Apple Watch. Maybe WWDC 2015 can get us the long awaited SDK.
  • Dropping the price given that they keep selling old hardware seems like a good move, and I would guess if a new OS with an SDK is comming implies that it will be supported.


  • The idea sounds great. I think using mobile devices for larger field samples makes sense, even if the sample is skewed in some ways.
  • I like that it’s Open Source. It shows they are doing it for a greater good rather than to sell more devices. But…
    • In the past, Apple has promised to standarize FaceTime and didn’t.
    • I dont’t think Apple has been a good steward of Open Source projects in the past. What I would love to see, is Apple commiting to develop ResearchKit in the open1. Open Source projects can’t be really open if they are only released alongside new OS versions and don’t have a somewhat public roadmap.


  • I’m glad it is still Intel and not ARM. I still need to boot into Windows from time to time, and I think that’s been one of the biggest benefits of the Intel transition.
  • I’m not sure I like them using a single USB-C port, but I understand the rationale: this is a MacBook designed with iPad ideas, and this makes sense in this context.
  • Using USB-C (an industry standard) is a great move. It will help move the adoption, as the original iMac did with USB, and lead to cheaper accessories in the near future. By the time all Macs have USB-C connectors, I guess will have a fair share of inexpensive hubs available.
  • Additional thought: what prevents Apple to move iOS devices to USB-C now? The connector looks small enough, and it’s standard. You could charge your iPhone with the same cable that came to charge your MacBook.
  • The new trackpad looks amazing. I’m courious how the Force Feedback settings work and feel.

  1. Showing a GitHub URL during the event would have nailed it.


Ever since announced, iOS devices stuck to a simple formula for storage sizes. You get the base model (8GB, 16GB depending when), and for USD 100 you can upgrade to the next storage tier. Storage tiers had been (up to 2014) twice the size each time, for example 16/32/64. Even if this was not logical to some1 it was somehow easy to understand: storage bumps were linear in their multiplier (2x, 2x).

This year, this changed for the worse. Apple is now offering all their new devices (iPhone 6, 6 Plus, iPad Air 2, iPad mini 3) with storage tiers of 16/64/128. When I first say this during the original iPhone 6 / 6 Plus introduction, I wrote:

I like that the middle tier is now 64GB, but dislike that the bottom one remained at 16GB. It strikes me as unfair, although I understand the reasoning to try to drive customers to a more expensive device.

I was able to now pinpoint why I dislike this. The following screenshot is taken from Apple Store, when you choose an iPad mini 2 and can see the offered data plans:

Each carrier has a different pricing structure, but the intent is clear: drag you away from the cheapest plan. AT&T is the more obvious one: the jump from 250MB to 3GB is huge. Sprint is similar (although it’s first plan is way better than AT&T’s): the first jump gives you 3x the data, while the second only doubles it.

My feel with iOS storage bumps is that Apple is applying a similar strategy to try to drive you to the second tier. It’s not unfair, as I qualified it. But it’s something I expect from cellular carriers, not from Apple.

  1. It never made much sense that the additional 16GB had the same USD 100 price that the additional 32 or 64GB for succesive bumps.

An idea: CloudKit for Family Sharing

CloudKit is the new syncing backend provided by Apple. Based on initial reviews and opinions, it appears to be great. I think, however, that there’s a low hanging fruit for Apple to take advantage of: CloudKit for Family Sharing.

As it works now, CloudKit provides two kinds of storages: Public and Private. Public storage is a huge DB shared among all the users of your app. It appears to be tuned or thought for apps like Instagram, where there’s a social graph and a large timeline.

The Private database is different: it works as part of each users iCloud storage and is limited in size by it. This appears to be tuned to syncing across devices. It has great use cases, and several apps could benefit from it (Vesper and Things come to mind).

Both options leave a slice of the sync market unattended: sharing private data with other users. Think of apps like Notabli, or our own Shopster, where the most requested feature is by far syncing with other members of your household.

Do you see a pattern yet? There’s a big chance that several of the common sharing cases are among people in the same iCloud Family Sharing setup. Which brings me to the original idea: it would be great to have a third1 CloudKit database for Family Sharing. This one would be similar to the Private database and count against the organizer space quota, and ideally a new API would allow you to easily move data from your private cloud to the family shared one.

This third option could go a long way to address a common sync need that is currently unsolved by what Apple offers2.

I’ve filed a bug report for this. If you think it may benefit you as well, feel free to use it as a reference.

  1. I don’t know the implementation details, but I guess it’s not really a third database, but flags on the actual CKRecords. This way, if you decide or have to stop Family Sharing, your data could still be part of your Private database.

  2. If Apple ever implements a feature like this, and given that iCloud Deive is claimed to be implemented on top of CloudKit, it wouldn’t be far fetched to think a shared “family folder” could also be added to iCloud Drive.

UITableViewRowAction Introduction

iOS 7 saw the introduction of a new style for the swipe to delete in table view cells. The entire cell content was placed in a UIScrollView, and swiping would reveal the red Delete button. iOS Mail (and only that app) also sported an additional More menu item. This API, however was private.

In iOS 8, Apple finally made this API public 1 for all of us to use, in the form of edit actions and UITableViewRowAction.


In order to provide your UITableViewCells with actions, you need to implement the method func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? of UITableViewDelegate.

The method retuns an array of actions. The order is of course important: the first item in the Array will be the rightmost (or leftmost on RTL user interfaces) item when you swipe the cell.

A sample implementation follows:

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {

    let deleteClosure = { (action: UITableViewRowAction!, indexPath: NSIndexPath!) -> Void in
        println("Delete closure called")

    let moreClosure = { (action: UITableViewRowAction!, indexPath: NSIndexPath!) -> Void in
        println("More closure called")

    let deleteAction = UITableViewRowAction(style: .Default, title: "Delete", handler: deleteClosure)
    let moreAction = UITableViewRowAction(style: .Normal, title: "More", handler: moreClosure)

    return [deleteAction, moreAction]

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

    // Intentionally blank. Required to use UITableViewRowActions

This is how it looks when you swipe:

As you can see you need to return an array of UITableViewRowAction objects. UITableViewRowAction.init receives three parameters:

  • style: either .Normal or .Default. .Normal doesn’t have a color, similar to the More button in iOS 7 Mail, and .Default is the standard destructive action, with the red background color.
  • title: the label that will be shown to the user when swiping the row.
  • handler: a closure (or block) with the handler that will be called when the action is selected by the user. The handler receives two parameters: the action itself, and the indexPath. Sadly, the handler doesn’t give you the UITableView as a parameter, so your handler needs to get a reference to that by other means.

As you may have noticed it in the sample code above: in addition to tableView:editActionsForRowAtIndexPath: you need to override tableView:commitEditingStyle:forRowAtIndexPath:, even though you can leave it blank. If the method is not present, the actions won’t show up on swipe2.

In case you find it useful, I’ve left the sample project I used for this post a GitHub repository.

  1. Interestingly, in iOS 8, Apple is again testing more UITableViewCell actions, like swiping across the entire row to trigger an action, or swipe from both sides to reveal different options. Additionally, it appears iOS 8 private API also allows you to customize the background colors. I’m looking forward to iOS 9 (or 8.1) making these API public.

  2. As you can see in my sample code, this method has a comment indicating it’s intentionally blank. Any time you need an empty method implementation leave a comment, as these methods will be the first you (or other teammate) will target for removal when refactoring code.

Apple Watch Event Thoughts

After a little more than a day, and digesting the latest Apple event, I figured I’ll write my first thoughts.

I haven’t yet checked the latest iOS Simulators, nor rewatched the event video. I’m writing this as bullet points, as I don’t have any coherent thought to run through all of them.

Overall it was an amazing event (even with the poor streaming), except for the U2 part at the end, which fealt overacted and uncomfortable.

Apple Watch

Ever since I got my first mobile phone I stopped wearing a watch. I do have a Fitbit One, that I like and use everyday.

  • It’s the first version. It the Watch success (and I think it will) it will be remembered fondly as the original iPod, iPhone or iPad.
  • It’s a sad fact that it needs to be recharged overnight (even more, it appears to be designed with that use case in mind). Fitness trackers are used to track sleep, and one of the features I like the most is their silent alarms, so you can wake up in the morning without waking up the rest of the family. I figure we’ll get there eventually with the Apple Watch.
  • I like how they made so many different bands and styles. I always considered a watch to be more about personal style than a phone, and I like how this is being addressed.
  • The watch creates a new entry point for a potential halo effect on the iPhone. Some people might get attracted to the watch more than to the iPhone, creating new potential customers for both.
  • We can always use more sensors. A gyro would be useful to measure stuff on a tennis or golf player for example. If the iPhone is any experience, sensors will be added.
  • I’m really curious on the update cycle for the watch. With no subsidy and potentially high prices, what’s the expectation on users updating their watches? How will that fragment the app ecosystem?
  • I’d love it to be thinner. Once again, I can see this happening sooner rather than later, as it did with the iPad 2.
  • I know about Option + Shift + K. Did you know about Simbol to type it on the iOS?

iPhone 6 and 6 Plus

  • They look big and great. If I were to pick one, I think I’d go with iPhone 6. The huge hardware change will certainly draw a lot of people to the iPhone, either switching from Android for the first time, or coming back after feeling dissapointed by smaller screens.
  • I like that the middle tier is now 64GB, but dislike that the bottom one remained at 16GB. It strikes me as unfair1, although I understand the reasoning to try to drive customers to a more expensive device.
  • 3x assets and the scaling is weird. I figure it’s a stop gap measure until we can get screens at 4x resolutions, so we can go back to pixel perfect assets if we wish to. While iOS 7 and 8 have a visual style that do not require pixel perfect mockups, iOS 7 was touted as designed for retina displays, and the recommendation was to use retina assets (like 1px lines) which might not look good on the 6 Plus.
  • It’s a sad reality, but the leaks during the buildup for these events keep being real. At this point, Apple can only either preannounce hard, as they did with the Apple Watch, or surprise us with software, as with iOS 7, Yosemite or Swift. It’s a bittersweet feeling: I like the huge reveals, but as a developer, I can also see the great value in revealing software that has the potential of changing the hardware we already own.

Apple Pay

  • I really love the focus on privacy. The fact that the credit card information remains on the phone is reassuring.
  • There are two steps that are moody for me:
    • How is the validation with the bank done? Will Apple have to partner with every bank that provides credit cards?
    • If credit cards are local to the phone, what happens when they add the card you have on file on your Apple ID? Is it transfered? Referenced?
  • Living in Argentina, I don’t see this coming soon here, but I’m certainly used to that.

  1. I understand “fairness” is not how this should be thought of, but an impression: 32 more GB are suddenly “free”, but 16 more for the smaller one are not…

Adopting Adaptive

One of my biggest takeaways of WWDC 2014 was Adaptive Apps. If you haven’t yet, you can check the video for session 216, Building Adaptive Apps with UIKit.

In the past days, there have been a few articles about it (I got to them via Brent Simmons):

Over the last three years (as I think is usual with Apple), we’ve seen a succession of technologies that we were “suggested to adopt”:

  • iOS 6 brought us Auto Layout, as a declarative way of creating constraints between our views.
  • iOS 7 introduced Dynamic Text, allowing users to easily tune the sizes of all the fonts in their devices.
  • iOS 8 is adding Adaptive Apps in UIKit and Presentation Controllers.

Adaptive apps are sold to us for two main reasons: supporting both iPhone and iPad with the same codebase with less specific cases, and supporting the new rotation. New device form factors are -of course- never mentioned in any WWDC session, nor is the ability to resize apps on an iPad, as apparently will be the case.

If the next iPhone indeed ships with a bigger screen, the main reason would be to have more content on screen at the same time, not to have something akin to an @3x. So, if we assume the screen will be bigger (to fit more content), we only have one question: will the screen have the same DPI as the existing iPhone?

Let’s explore the ramifications of each option.

Same DPI as iPhone 5s

Ever since the original iPhone, objects on screen have had the same physical size. The move to retina only increased the pixel count, but the actual size remained the same.

Keeping the same DPI will be an impact similar to when the iPhone 5 shipped: our apps will need to adapt and show more content. If the phone is wide enough, there’s a chance the Horizontal Size Class in Portrait of this new device changes to Regular as opposed to Compact, and our apps will need to adapt to it (UISplitViewControllers will became more common, for one). With the same logic, the Vertical Size Class in Landscape might change to Regular.

All in all, this change will probably be the easier to deal with, as typography and images will look the same.1

Higher DPI than the iPhone 5s

As I tweeted to Brent Simmons, here’s where I think it gets interesting.

If Apple wants to have the text look the same size, they might tune the Dynamic Text default sizes on the new device to compensate for the higher DPI2.

On session 226, What’s new in Table and Collection Views you can see how they use the multiplier in Auto Layout constraints so that UITableViewCells change in height as the Dynamic Text size changes, and look better when bigger fonts are in use. I can see this approach being the recommended way forward, basing the layout around the text sizes, so Apple can tweak them based on the hardware they ship.

Other thoughts

What about userInterfaceIdiom?

My notes from session 216 were that UIUserInterfaceIdiom was deprecated. What they actually said is:

In the past you’ve used UIInterfaceOrientation and UIUserInterfaceIdiom to differentiate between portrait and landscape and iPhone and iPad, but in iOS 8, we’re recommending against using these two concepts, and instead we’re advocating this > new concept that we call size classes.

(source: asciwwdc.com)

Yet, UITraitCollection contains a userInterfaceIdiom trait. Why was this kept, if Apple is suggesting against basing the UI based on the device? My understanding is that it’s there because we’ll still need it to determine the intent of the user. Our apps need to know if the user has launched our app on his iPhone, probably on the move or doing something else, or on an iPad, where we can assume he’s more comfortable and about to have a longer use session.3

Business implications

I don’t think there’s a huge business implication for this right away. If you want to ship to separate apps for iPhone and iPad, I don’t expect Apple to prevent you from doing it.

However, since you’ll have to support iPhones with multiple screen sizes, it’s very possible that going from a multi-sized iPhone app to a Universal app will be a simpler transition. This, I’m confident, might have the nice outcome of combating what Marco Arment called App Rot and provide more quality universal apps for the users.

Implications for font heavy apps

There are some apps that rely a lot on custom fonts, such as Vesper. Since Dynamic Text does not allow you to use custom fonts, I wonder how those apps will work around a different Dynamic Text default size. There are tons of valid workarounds, like fetching the system font size and base your custom font size on it, but an Apple blessed solution would do a lot to help in this direction.4

  1. Any given text, at the same Dynamic Text setting will look the same on the iPhone 5s and on the new iPhone.

  2. I’m assuming the new device still runs with a display scale of 2.0, as the retina screens we currently have.

  3. I first thought this had to do with device capabilities, such as to tell if the app needs to highlight phone numbers or not. I think that’s a blurrier line, as we don’t know what capabilities future devices will have, and well behaved apps need to check for specific capabilities instead, not make assumptions based on the userInterfaceIdiom.

  4. While I’m not sure what the best solution is, I’ll be happy to have something similar to a very simple CSS file, where you can specify for each Text Style the font name, size and weight you want it to take.

iOS 8 - More than I expected

Before leaving for WWDC 20141, I wrote a small post with my iOS 8 Wish List. I’m glad to say that the announced features of iOS 8 cover way more than I expected. I’ll break it up in the same major features I expected, and see how the announced features fit.

Multi User Support on the iPad

On my wish list, I wrote:

Ever since the first launch of the iPad, multi user support was a rumored feature. I always thought Apple’s rationale behind not providing multi user support was two-fold: it would add complexity to the platform, and it might take away some sales (why get a second iPad if I can just create a user for the kids?).

While we did not get multi-user support, we got Family Sharing. Instead of focusing on sharing the physical products Apple is focusing on sharing the digital assets. Its a different problem to take on, but at least it acknoledges the same underlying problem: some households might have a multitude of iOS devices and users.

With Family Sharing, Apple is making it simpler to do what we already do: share our purchases with other members of our family. We do it by sharing a main Apple ID to make purchases. Now it will be easier to do, and I’m glad.

As for Multi-User Support on the iPad, it is still missing, but I guess if we are ever going to get it, having Family Sharing in place before might make things simpler later.

Some sort of File Management

I was pessimistic on this one:

Sadly here, I don’t see Apple doing any sort of File Manager on iOS. Even more, I think they are moving in the opposite direction with iCloud storage on Mac apps, where each file type is tied to the app that created it. But given that this is my wish list, I figure it’s fine to dream.

Not only Apple is backtracking with its Documents in the Cloud approach (the new iCloud is closer to Dropbox than to the old iCloud), but they are allowing third party apps to be document providers by means of extensions.

This is huge. It has the potential to create lots of new use cases, and even some that we can’t imagine but will only realise were possible when we see the app in the store.

From all the Extension types iOS will now allow, this can prove to be the biggest game-changer for the OS.

System Contributions from apps

I missed the obvious name here, but Extensions are amazing and provide more than what I imagined. I always imagined Share Extensions and Notification Center widgets to be something obvious, but I never expected Photo Editing (with in place modifications), third party keyboards or the new features for document management.

This is great, and really opens the door for amazing new apps and use cases.

OS X / iOS integration

When I imagined this, I don’t think I was aiming as high as the iOS 8 team is with Continuity. I expected a few simple things:

  • Trigger certain notifications only when your phone is away from the Mac.
  • Establish a secure link between the Mac and iOS and use Touch ID to unlock your Mac.
  • Have an iPad act as an AirPlay display if you want to, etc.

Instead of this, we got something bigger and better:

  • There is some great integration of devices, as I expected. This is what allows you to get SMS’ on your Mac, or have the iPhone dial a phone number.
  • Handoff will allow third party apps to allow users to continue what they were doing on another device. This even works between a mobile app and a website, by registering your URL with Apple. I can’t count the times I emailed myself a draft I was writing on the iPhone only to later complete on the Mac and send it.

There’s way more stuff in iOS 8 than what I covered here. But given my short wish list, I can say Apple nailed almost every feature I wanted and then some. I really look forward to both be a user of some of these features, and be able to have some users benefit from these in apps we create.

  1. I’m yet to write my WWDC post. It was such an amazing experience, that I’ve found it hard to write about. I’ll try to make it up soon.