This is Burpple's Swift Style and Conventions Guide.
The purposes of this document are
- to improve code readability
- to have common rules in dev team
You can write flixible code using Swift, though, it's hard for team development to standardize and to improve readability. This is the reason why we are making this document. Of course as we are still improving and looking for good ways, if you have suggestion, let us know and open a pull request :)
This document is open to anyone who wants to contribute.
Xcode 6.1.1, Swift 1.1
v0.1.0
Use tabs, instead of using spaces
Place 1 space before the leading brace, the return value, the return arrow
// good
func hello() {
}
// good
func hello() -> String {
return "hello"
}
// bad
func hello(){
}
// bad
func hello() ->String {
return "hello"
}
Place 1 space after the colon
// good
let name: String
// bad
let name:String
Place 1 space after the comma
// good
func hello(name: String, message: String) {
}
// bad
func hello(name: String,message: String) {
}
Operator with 1 space
// good
let x = 1 + 1
// bad
let x=1+1
// MARK: - HelloWorld
When declaration is with right side value, you don't need to specify the type
// good
let message = "hello"
// bad
let message: String = "hello"
But if right side value is ambiguous, you should specify the type
// you can't tell the type of the right side value. CGFloat, Float, Double?
let value: CGFloat = 1.0
If right side value is return value which you can't tell the type explicitly, you should specify the type on the left side
let result: Bool = delegate.writeGreatCode()
But if return type is obvious, you don't need to specify the type on the left side
// it's obvious that return value is UIApplication's instance
let application = UIApplication.sharedApplication()
Also if use cast, you don't need to specify the type on the left side
// good
let movie = object as Movie
// bad
let movie: Movie = object as Movie
Use weak and unwrapped type to define IBOutlet
// good
@IBOutlet weak var headerView: UIView!
// bad
@IBOutlet weak var headerView: UIView?
// bad
@IBOutlet var headerView: UIView!
If the value won't be changed afterwards, use let.
Use Swift style
// good
"I am \(name)"
// bad
NSString(format: "I am %@", name)
- String is Struct, NSString is Class
- Use Swift native type, which is String, whenever possible
- Convert from String to NSString when you want to use NSString method
("test" as NSString).XXXXXX
Use Swift native type, Int, UInt, Float etc, whenever possible
When you need to use CGFloat, like when you make CGRect, convert Float to CGFloat
var f: Float = 10.0
CGRectMake(CGFloat(f), 0, 10, 10)
- Array is Struct, NSArray is Class
- Use Swift native type, which is Array, whenever possible
Follow Apple official document
// good
var someInts = [Int]()
// bad
var someInts = Array<Int>()
Use for-in style
// good
for value in array {
}
// bad
for var i = 0; i < array.count; i++ {
let value = array[i]
}
- Dictionary is Struct, NSDictionary is Class
- Use Swift native type, which is Dictionary, whenever possible
Follow Apple official document
// good
var namesOfIntegers = [Int: String]()
// bad
var namesOfIntegers = Dictionary<Int, String>()
- Copied when passed as an argument to a function
- Copied when assigned to a different variable
- Immutable if assigned to a variable with let
- Stored in the heap and reference counted automatically
- when passed as an argument, doesn't make a copy(just passing a pointer to same instance)
- Usually choose class over struct. struct tends to be more for fundamental types
If return value is Void, you don't need to specify return type
// good
func doSomethingGreat() {
}
// bad
func doSomethingBad() -> () {
}
If return value is Void, you don't need to specify return type
// good
var closure = { (value: String) in
println(value)
}
// bad
var closure = { (value: String) -> () in
println(value)
}
If you access to a property or method, write "self" explicitly
// good
func doSomethingGreat() {
self.doSomethingGreater()
}
// bad
func doSomethingGreat() {
doSomethingGreater()
}
##Statements
You don't need to write ()
// good
if x == 1 {
}
// bad
if (x == 1) {
}
Use for-in style
// good
for value in array {
}
// good
for index in 1...5 {
}
// bad
for var i = 0; i < array.count; i++ {
}
Any functions that are expected to mutate the receiver should be marked mutating
protocol SomeProtocol : InheritedProtocol {
mutating func changeIt()
}
When you declare property and set initial value, initialize it in init
// good
class Person {
var age: Int
init () {
self.age = 20
}
}
// bad
class Person {
var age: Int = 20
}
If a property is initialised in init, you don't need to use Optional, Unwrapped Optional Type
// good
class Person {
var name: String
init () {
self.name = "Swift"
}
}
// bad
class Person {
var name: String!
init () {
self.name = "Swift"
}
}
// bad
class Person {
var name: String?
init () {
self.name = "Swift"
}
}
If a property initialised in loadView, viewDidLoad, awakeFromNib (setup methods), you can use unwrapped optional type
// good
class SwiftViewController: UIViewController {
var name: String!
override func viewDidLoad() {
self.name = "Swift"
}
}
// bad
class SwiftViewController: UIViewController {
var name: String?
override func viewDidLoad() {
self.name = "Swift"
}
}
TODO: implementing...
TODO: implementing...
TODO: implementing...
As this feature is easily abused
- Extensions should be used to add clarity to readability
- Don't use this feature as a substitute for OO design
TODO: implementing...
TODO: implementing...
- init
- convenience init
- weak, unowned
- Access Control
- Log etc
The Swift Programming Language
Developing iOS 8 Apps with Swift.