Skip to content

Commit

Permalink
add my swift style ideas
Browse files Browse the repository at this point in the history
  • Loading branch information
jqsilver committed Jan 8, 2016
1 parent 0c2c83b commit c93ee5a
Showing 1 changed file with 195 additions and 0 deletions.
195 changes: 195 additions & 0 deletions swift.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,198 @@

*Swift*

# Swift Style Guide

* capitalize constants, and prefer putting them in the top level of a class if they are private. If they are public, put the constant as a static property, so we get nice namespaces.
```swift
private let PrivateValue = "secret"

class MyClass {
static let PublicValue = "something"

func doSomething() {
print(MaxTime)
}
}
```

* always use “self” for properties. Don’t use it for methods.
```swift
class MyClass {
var aProp: Int

func doSomething() {
// WRONG
aProp = 4

// RIGHT
self.aProp = 4

// WRONG
self.otherMethod()

// RIGHT
otherMethod()
}
}
```

* Try to initialize properties in the init() method whenever possible, rather than using implicitly unwrapped optionals. (Notable exception is UIViewController.)
```swift
// WRONG
class MyClass: NSObject {
var someValue: Int!
init() {
super.init()
someValue = 5
}
}

// RIGHT
class MyClass: NSObject {
var someValue: Int
init() {
someValue = 0
super.init()
}
}
```

* Use functions instead of computed properties if they get to be complicated. Also avoid didSet and willSet for the same reason.
```swift
// WRONG
// this is less readable
class MyClass {
var someValue: Int {
get {
// return something computed
}
set(newValue) {
// set a bunch of other values
}
}
}

// RIGHT
// easier to read more clear that there are side effects of setting
class MyClass {
func someValue() {
}

func setSomeValue() {
}
}
```
* Separate long function names on each argument and put the open curly on the next line so the body is indented correctly.
```swift
class MyClass {
// WRONG
func doSomething(arg: Int, anotherArg: Int, yetAnotherArg: Int, andOneMoreArgForGoodMeasure: String) {
// This is just too long and will probably auto-wrap in a weird way
}

// WRONG
func doSomething(arg: Int,
anotherArg: Int,
yetAnotherArg: Int,
andOneMoreArgForGoodMeasure: String) {
// XCode will indent the body an extra level in
}

func doSomething(
arg: Int,
anotherArg: Int,
yetAnotherArg: Int,
andOneMoreArgForGoodMeasure: String)
{
// Will cause correct level of indentation
}
}
```

* Avoid large callback blocks - instead organize them into methods. This makes weak-self in blocks much simpler.
```swift
// WRONG
class MyClass {
func doRequest(completion: () -> Void) {
API.request() { response in
// lots of processing and whatever
completion()
}
}
}

// RIGHT
class MyClass {
func doRequest(completion: () -> Void) {
API.request() { response in
self.processResponse(response)
completion()
}
}

func processResponse(response) {
// do actual processing here
}
}
```
* Guard
* Only add to top of functions. Goal of guard is to reduce branch complexity and in some ways adding guard statements in the middle of a chunk of code increases complexity

* How do we deal with multiple let clauses in an if clause?
```swift
// This feels weird, but is how autoindent works right now in XCode
if
let val1 = val1,
let val2 = val2
where !val2.isEmpty {
print(val2)
}

// Putting the first let on the same line as the if makes the body indent an extra level
// This also looks kind of gross
if let val1 = val1,
let val2 = val2
where !val2.isEmpty {
print(val2)
}
```
* Don’t include return type Void in blocks even though that’s what autocomplete does
```swift
// WRONG
someAsyncThing() { argument -> Void in ... }

// RIGHT
someAsyncThing() { argument in ... }
```

* prefer immutable values whenever possible. use map and flatmap instead of appending to a new array. mutable variables increase complexity, so try to keep them in as small a scope as possible if you have to use them.
```swift
// WRONG
var results = []
for element in input {
let result = transform(element)
results.append(result)
}

// RIGHT
let results = input.map(transform)

// WRONG
func doSomething() {
var someHash = getHashFromSomewhere()
someHash["someNewKey"] = someComputation()
doSomethingWithHash(someHash)
}

// RIGHT
func doSomething() {
let someHash = getHashFromSomewhere()
let modifiedHash = modifyHash(someHash)
doSomethingWithHash(modifiedHash)
}
```
* Avoid using optionals unless there’s a good semantic meaning.


0 comments on commit c93ee5a

Please sign in to comment.