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.
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!