AMScrollingNavbar: Creating a Cocoapod
This week Matt Thompson published an interesting article on NSHipster, about stewardship, which is basically the duty and ethic of public service. Since I’ve been trying to be more active in the open source community, I figured I could use this occasion to write an article with the process that I follow when I’m writing a new library for iOS. I’ll be describing my work on AMScrollingNavbar as an example.
AMScrollingNavbar is a simple iOS library that lets you implement a
UINavigationBar that scrolls out of the way when the user is scrolling the content of the app. You can observe this behavior in Google Chrome, Instagram or Facebook apps. I wanted to integrate something like that on one of the app I’m working on, over at Fancy Pixel, but couldn’t find anything that did the job as I intended. What better motivation to do some OSS?
Writing the code
In cases like this, writing the code is more a series of trial and error, so instead of TDD I use a more sample driven approach. This means that I just fire up XCode, create a new project and start fiddling around with the SDK. That’s the best part of the job.
UINavigationBar scroll out of the way was fairly easy, I just needed to add a
UIGestureRecognizer to the
UIScrollView with the content.
1 2 3 4
That alone won’t do the trick though, we need to override a delegate method of the
1 2 3 4
YES in this method will allow both the scrollview and the gesture recognizer to work at the same time. Cool.
Now it’s time to stretch
UINavigationBar’s leg. Here’s an abstract of the code that does that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
As you can see the
UINavigationBar has its own frame, that you can easily modify. Once I got the navigation bar following the scroll view, I needed to enlarge or reduce the scroll views’ frame to leverage all the remaining screen estate. Big chunk of code coming up:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Fairly easy to read, kinda tricky to write. The scrollview’s height is increased by the scroll’s delta, and its origin is shifted up or down of the same amount. With a little reflection I can check wether the scroll view is a normal
UIScrollView (and this includes table views) or a
UIWebView. The later has its own scroll view, so I need to adjust that instead.
With the view sizing complete, the last step was to fade out the navigation items. I used a hacky approach, since I wasn’t able to set the alpha channel of every nav item, I figured I could just impose an overlay view with the same
barTintColor, and change its alpha back and forth:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
And that did the trick.
Getting camera ready
Once the sample runs like I intended, I step in the refactoring phase. In this step I just take all the code and move it in a reusable object. In this case I opted for a
UIViewController that can be subclassed by other developers. I valued the possibility of a category, but since I make an extensive use of instance variables, I preferred the first approach (not a fan of the
The last item on the todo list is the refactoring of the sample project. And we’re done.
Writing the documentation
An open source project is as good as its documentation is. It helps the first implementation by other devs, and most of all helps them decide wether to use your library or not. In some way it’s marketing, without the market part.
I like to spend some time to add comments following the Appledoc notation. This will provide a comprehensive quick guide in XCode, and also will generate an Apple-like documentation in the Cocoapods pages. As you can see the syntax is easy to write and to understand:
1 2 3 4 5 6 7
Then it’s time to push all the work on Github, and this calls for a good README file. The README should have a quick description of the library, the setup instructions, the library’s documentation or a reference to it, and a screenshot, when possible.
Following the principle “show, don’t tell”, screenshots work great, but GIFs are even better. Creating a GIF animation with your sample running is easy as pie, using LICEcap. Despite its weird name and lowres icon, LICEcap is an invaluable tool, easy to use and extremely versatile, you just fit the portion of the screen that you want to record inside its window, hit record, and you are done.
You might want to resize the output GIF, if you are capturing a big part of the screen, or if you are working on a retina display. ImageMagick comes to the rescue:
Travis CI is a continuous integration tool, used to build and test projects hosted on Github. Having Travis enabled in an open source project is a great way to make sure that your project compiles fine. This is awesome for your new releases (you know before hand if your last commit broke something) and even better for pull requests, since Travis tells you wether a pull request compiles without errors, directly in the github page of the PR.
To start using Travis, head here, login with Github, and enable your project from the list in your dashboard.
Enabling Travis with iOS is really easy, it only takes two steps:
Configure build scheme
Open your sample project, or the project component that you want to build, and in the Manage Schemes panel, make sure that your project scheme is
.travis.yml file in your project root. You’ll be writing a simple script that will compile your sample project:
1 2 3 4
install phase just changes the directory to the one containing the project, then our trusty xctool compiles the project. Doesn’t get much easier than that.
Once you pushed the new release, the project will be added to the travis compile queue, and you’ll receive an email with the result. You can also see the script running in real time, which is awesome.
There is no need to reiterate that Cocoapods is great. The times when you spent precious time configuring a new library in your project are (almost) over. Creating a pod is a matter of minutes, and at the same times provides great value for the community.
You’ll find a pretty extensive guide on the cocoapods site. Here’s what my podspec looks like:
1 2 3 4 5 6 7 8 9 10 11 12
Once the spec is merged in the Spec repo, a new pod is born, and with it the documentation page is also generated.
Cocoacontrols is my favorite place to window shop for new libraries. As soon as my pod is ready and I feel that the README is comprehensive enough, I submit my control to cocoacontrols’ review queue. It’s a great way to get some visibility from fellow developers, and a great way to discover new controls. A big thanks to Aaron, Marine and Bob.
Maintaining the code
Once the code is in the wild, it’s time to maintain the code. This means answering questions about its use, fixing possible issues and merging the always welcome pull requests. It can become a job of its own at times, but it’s a high reward task, since it gives you the chance to experiment more and improve your code quite a lot.
The only tool that I use is the
Issue section of github. I tried once to get into the habit of tracking the issues with Waffle, but in the end I never really used it efficiently.
AMScrollingNavbar was well received, and has now (what is for me) a fair amount of stargazers on Github. I’d like to thank all the contributors that helped to improve the library, introducing new features and fixing my missteps.
That about wraps up this auto referential post.
Until next time.