Swift API Design Guidelines

Swift 3 is a reevaluation of the past 2 years and changes a lot from previous versions


– Clarity is more important than brevity on the code

Strive for clear usage, omit needless Words

Too vague

Too specific

Removing needless words, if a word is not contriuting to the clarity of a usage, remove it

Getting towards to having clear code that is concise

What words are needed?
myView.addChild(view, atPoint:origin)

The specification of Child is important, as it gives the context of hierarchy for the parameter

myView.addChild(view, atPoint:origin)

Since the method already gives a strong type for the parameter, the method can only recieve CGPoint, so there is no need to respecify that we are passing a point via paramter. It doens’t give additional information.

myView.addChild(view, at:origin)


Claryfying the behaviour of the api
By adding
friends.remove(ted) remove(_:)
friends.remove(at: formerFriendPosition) remove(at:)

In swift a method is comprised by base name “remove” as well as the argument labels. Both methods are in the same method family and they specify via the paremeter label.

In Swift you can overload methods, only if it is essentially the same operation only overloaded with different types:
text.append(aCharacter) // append(_:)

Examples where to add a parameter label, as general rule, when it helps to read well gramatically:
truck.removeBoxes(withLabel: "A label")
viewController.dismiss(animated: true)
friends.insert(michael, at: friends.startIndex)

Mutating vs non-Mutating
The “ed/ing” rule
x.reverse() //mutating
let y = x.reversed() //nonmutating

documentDirectory.appendPathComponent(".list") // mutating
let documentFile = documentDirectory.appendingPathComponent(".list") //non mutating

New API/Two Names
One name that is appropiate for Objective-C and one for Swift

Objective-C “Stringly typed” method names
in Swift 2.2:
controller.addTarget(self, action: #selector(handleDrag(sender:for)))

New in Swift 3:
self.perform(#selector(setter: Artist.name))

Keypaths (Pound keypaths)
instead of:
album.addObserver(self, forKeyPath:"artist.name")
album.addObserver(self, forKeyPath:#keypath(Album.artist.name))
Compiler validates that are Objective-c properties produces the name to pass it down to the frameworks

For mixed projects (Obj-C + Swift) some namings might not be good for one or another language

extension MyController{

func handleDrag(sender: UIController, for event: UIEvent){} //handleDrag(sender:for) doesn’t make to much sense for Objective-c, use annotation to specify the objective-c name

Generated Objective-C from above

@interface MyController()
- (void)handleDragWithSender:(UIControl *)sender for:(UIEvent *)event;

Translate to Swifty APIs
Automatic translations with Swift compiler
1) inspects method names and use gramatic queues to infer first parameter labels
func saveToURL(_ url:String)
func save(toURL url:NSURL)

2) inspects names to remove reduntant information
func save(toURL url:String, forSaveOperation saveOperation: UIDocumentSaveOperation)
func save(to url:NSURL, for saveOperation:UIDocumentSaveOperation)

3) Infer default values for common objective-c idioms, like completionHandlers or option sets
func save(to url:NSURL, for saveOperation:UIDocumentSaveOperation, comletionHandler: ((Bool) -> Void)? = nil)

4) New bridging value types like URL that bridge the Objective-C Objects
func save(to url:URL, for saveOperation:UIDocumentSaveOperation, comletionHandler: ((Bool) -> Void)? = nil)

Translate “stringly” typed API to swifty (ish) API
NS_EXTENSIBLE_STRING_ENUM to transform stringly typed objective to swift
NSString *NSCalendarIdentifierGregorian = "gregorian"
typedef NSString *NSCalendarIdentifier NS_EXTENSIBLE_STRING_ENUM
NSCalendarIdentifier NSCalendarIdentifierGregorian;

Generated Swift
Transformed to Strongly typed
struct NSCalendarIdentifier: RawRepresentable{
init(_ rawValue:String)
var rawValue: String{ get }
static let gregorian:NSCalendarIdentifier

let cal = NSCalendar(identifier: .gregorian)

with bridge
let cal = Calendar(identifier: .gregorian)

Translate C API into Swifty API
NS_SWIFT_NAME import globals as members of type

CFStringRef kCGColorWhite NS_SWIFT_NAME(CGColor.white)
Generated Swift
extension CGColor{ static let white:CFString }
Swift use
let color = CGColor.white

CGAffineTransform CGAffineTranformMakeTranslation(CGFloat tx, CGFloat ty) NS_SWIFT_NAME(CGAffineTransform.init(translationX:y:));
Generated Swift
extension CGAffineTransform{ init(translationX: CGFloat, y: CGFloat) }
let translat = CGAffineTransform(translationX: 1.0, y: 0.5)

Complete example:

From this:

Screen Shot 2016-06-15 at 17.17.42


To this:

Screen Shot 2016-06-15 at 17.17.29


Leave a Reply

Your email address will not be published. Required fields are marked *