Tips for Writing a Great iOS Framework

With the rise of Cocoapods and the upcoming Swift Package Manager, a lot of devs are trying their hands at writing a framework/library for other developers to use (and that’s great, and you should!). However, writing a framework has a different mentality from writing regular app code, and there are a few tricks and tips worth knowing.

I’ve been working on a framework for a little over a year now, and have learned some things along the way.

Namespace your Code

Namespacing, the act of putting a few letters in front of our class name, is a big step in preventing collisions with other code. This is typically done with the author or Apple's name. For example, I could prefix my code with SAJ, so I would have SAJAppDelegate,SAJMyModel,SAJMyViewController as classes. For frameworks, 3 letter prefixes is best (thanks to those who pointed this out to me on twitter!).

Another place to do this, that people often forget is in your category methods. I recommend a 3 letter prefix before all category methods.

So, if you were to add a method to NSDate via a category that returned the nearest public holiday, you should name it something like saj_nearestBankHoliday, calling it like NSDate *easterFriday = [NSDate saj_nearestBankHoliday]; 

Use Nullability Annotations

For developers using Objective-C, one thing you can do to really give some love to your Swift users is to use Nullability Annotations. This will allow Swift users to properly know if properties, return values and arguments are able to be null or not.

@property (nonatomic, strong, nullable) NSString *firstName;

- (void) greetPerson:(nonnull NSString *) personName { ... }

Use Generics

Another great way to to enhance the experience of Swift developers is to use generics. This allows you to specify a type of object that goes in things that typically accepted any ol' subclass of NSObject. Swift users will get a real object, rather than [AnyObject], which they don't have to cast to use properly. Yay.

For example, you can now specify an array is only full of strings

@property(nonatomic, strong, nonnull) NSArray<NSString*> *names;

which will turn into

[NSString] in Swift.

Document Thoroughly

I might sound like a broken record now, but this is something a lot of developers simply don't put in the time to do. Write some damn comments. At the minimum, you should be writing documentation in all public header files, and if all source is exposed, on every method.

Things to include: params, return values, warnings, discussion, related methods

Bonus Tip: Use AppleDoc syntax, and CocoaPods will put you on CocoaDocs automatically.

NSHipster has a good article on this.

Never Assume What Thread You're Running On

Long story short, you don't get to control the instantiation of your classes or code when you're a framework. A lot of developers may choose to boot up your framework in the background after launch – so does this mean your app will crash? Does it touch the UI assuming it's on the main thread? In general, if your framework isn't touching the UI, it should run on a background thread and return to the main thread only when necessary so as to not slow down the host app. Be a good citizen.

More help.

Consider Xcode Version

When you're a framework, you have two users - The user of the App and the user of your code. Their tools, set up and stack may influence the design of the framework  - so be mindful of this. If you rely on features (such as those in newer versions of Xcode) you might be out of luck, since a lot of developers don't roll with the latest.

A while ago I did a survey and wrote about Xcode version, so have a read.

Enable Bitcode

Enable Bitcode!!! Seriously. An app can only support bitcode if all the included frameworks do too. So turn it on, and fix what you need to. You don't wanna be that one framework which means the app can't support bitcode. It's a fast way to be replaced.

Good Release Notes

Seems obvious, but it's something a lot of developers forget to do. Keep a public changelog. If you're all hip and use Github, just use the release page in combination with git tags. A good release notes log will help developers track progress of bugs, find stable versions and keep up to date. If they "watch" your repository, they'll get an email with release notes, too!

Example 😏


So that's it. A quick summary of some suggestions to make a better framework. Generally speaking, you need to think a bit harder than just what you're solving in code. Think about the developer experience (DX).

What are your tips? Ping me on twitter - I'm @samjarman with your thoughts! I'd love to hear them.

PPS: Michael, below, wrote a similar article. Check it out! 

What Version of Xcode Are You Using?

As a library developer for iOS Apps, it is always important to be aware what version of Xcode my users (other iOS devs) are using. This allows us to take advantage of new IDE features, but also support those who are lagging behind.

To assist with this, yesterday I did a quick poll on Twitter and asked — what version of Xcode are you using?

The Results

[embed]https://twitter.com/samjarman/status/686297486265192448[/embed]

Thanks to those 65 people who responded! :D

A total of 65 developers responded with 95% of people saying they use Xcode 7 or higher. This is by no means a large sample size, but it’s its certainly a good indication of where people are heading.

What this means

In Xcode 6.3, Nullability annotations were added to Objective-C. This allows you to decare whether properties, return types or arguments can be nil or not. This gives you more power when declaring your objects and their methods and properties. If you’re using Objective-C code from Swift, this converts nicely into optionals. That is to say, using nonnull or nullable will directly influence the appearance of ! and ?. Read more.

In Xcode 7, Objective-C gained support for both Generics and Kind Of annotations. This means you can both express and restrict the type that arguments can be and once again, this helps out Swift users too! No more [AnyObject]. Read more.

So, if you know which version of Xcode your users are on, you can roll out these features to them and improve their experience because as a library developer, your goal should always be a delightful developer experience.

So with this knowledge, go forth and make your library even more awesome!

Developers, let’s talk about 3D Touch

So at their September Event, Apple announced 3D Touch — a feature whereby if you push hard enough on your iPhone 6S or 6S Plus, you’ll get a new interaction style. Cool!

New Interaction Styles

There are two new styles that Apple has by default on some built in apps.

Home Screen Quick Actions

These allow for quick shortcuts into certain parts of your app — for example, jump to Beats 1 in  Music, or straight to the forward facing camera in the Camera App (Take a “Selfie”) by 3d touching the application icon.

Peek and Pop

Peek and Pop lets you “peek or “preview some content, whether it be an email or a message or something else. Once you decide you want to keep looking at it, or start interacting with it, you can “pop” it, making it open like normal for interaction.

3D Touch for Developers

You Can Use It

Apple has opened up their API for developers to add 3D Touch features to their apps. They can support Peek and Pop, Home Screen Quick Actions, and more! This is pretty exciting. In fact, a friend and The Next Web writer Owen Williams wrote an article about how he thinks it could be end the of the “hamburger” menu. While I don’t disagree with that, I think it’s time to slow down for a second and talk about 3D Touch to make some things clear.

Consider Apple’s Plan

If you think about the user experience Apple is providing with 3D touch, it’s clear to see they’ve laid out a roadmap for onboarding users to 3D Touch. The features above, Peek and Pop and Home Screen Quick Actions can be thought of as features that enhance the experience of iPhone 3D touchusers but doesn’t take away from the experience of other users. These are new ways to access already existing features, like composing a message or taking a selfie — they are not the only way to access a feature. It’s subtle, beautiful and useful.

Don’t Be Exclusive

If you make a feature exclusively or only accessible by 3D touch, it actually harms the experience to users not using that model of phone. Access to menus, features or screens via 3D Touch only is a big no no, as your users without 3D touch won’t be able to access it. Apple recommends at least one other way to access the feature — it could be as simple as treating tap and hold the same as a 3D touch.

Another thing to note is that 3D touch can be disabled via the accessibility settings (which makes sense) — so don’t assume that since they have one of the phones, that they’ll have the feature. Check for it properly.

Help With Discoverability

3D Touch is notoriously hard to discover, and it’s fair to say that some users will need to be explicitly taught that it’s there. Use an Onboarding systemfor 3D touch users so they learn how to interact with your app. The thing here is, that if you do this, it’ll train users to expect this functionality in other apps as well as stock apps — making them even more productive on their device. And they learned that from you. They’ll appreciate that.

Promote the New Paradigm

3D touch is a user interface paradigm now, like hamburger buttons, back buttons, or compose items — they’re something users will learn, recognize and expect consistent behaviour from. It’ll take a while to catch on. Be a good citizen and do what you can to help. By the way, this doesn’t have to be in code, show your friends they can do that on their phone too.

Conclusion

Developers, take advantage of these new features if you can. Make sure Peek and Pop work for your app, and use your analytics or common sense to determine what most common features you should put on your Home Screen Quick Actions list. Add new features to enhance the experience anddelight the users of 3D touch, but don’t assume all users have 3D touch for a few years at least. Lastly, help onboard your users into 3D touch to help with it’s discoverability as a system and app paradigm. Together, we can continue to delight our users. Good luck.