|
| 1 | +# SwiftCodingStyle |
| 2 | + |
| 3 | +###Constants and Variables |
| 4 | + |
| 5 | +Swift constants and variables associate a name with a value of a particular type. The value of a //constant// cannot be changed once it is set, whereas a //variable// can be set to a different value in the future. |
| 6 | +```swift |
| 7 | +var x = 1.2 |
| 8 | +let isBlue = true |
| 9 | +``` |
| 10 | +### Make use of constants over variables |
| 11 | + |
| 12 | +Use ''let foo = …'' over ''var foo = …'' wherever possible (and when in doubt). Only use ''var'' if you absolutely have to (i.e. you know that the value might change, e.g. when using the ''weak'' storage modifier). |
| 13 | + |
| 14 | +//Rationale:// The intent and meaning of both keywords is clear, but //let-by-default// results in safer and clearer code. |
| 15 | + |
| 16 | +A ''let''-binding guarantees and //clearly signals to the programmer// that its value is supposed to and will never change. Subsequent code can thus make stronger assumptions about its usage. |
| 17 | +It becomes easier to reason about code. Had you used ''var'' while still making the assumption that the value never changed, you would have to manually check that. |
| 18 | +Accordingly, whenever you see a ''var'' identifier being used, assume that it will change and ask yourself why. |
| 19 | + |
| 20 | +### Avoid using force-unwrapping of optionals |
| 21 | + |
| 22 | +If you have an identifier ''foo'' of type ''FooType?'', don't force-unwrap it to get to the underlying value (''foo!'') if possible. |
| 23 | + |
| 24 | +Instead, prefer this: |
| 25 | + |
| 26 | +```swift |
| 27 | +if let foo = foo { |
| 28 | + // Use unwrapped `foo` value in here |
| 29 | +} else { |
| 30 | + // If appropriate, handle the case where the optional is nil |
| 31 | +} |
| 32 | +``` |
| 33 | +Alternatively, you might want to use Swift's Optional Chaining in some of these cases, such as: |
| 34 | + |
| 35 | +```swift |
| 36 | +// Call the function if `foo` is not nil. If `foo` is nil, ignore we ever tried to make the call |
| 37 | +foo?.callSomethingIfFooIsNotNil() |
| 38 | +``` |
| 39 | +//Rationale:// Explicit ''if let''-binding of optionals results in safer code. Force unwrapping is more prone to lead to runtime crashes. |
| 40 | + |
| 41 | +###Avoid using force casting |
| 42 | + |
| 43 | +Prefer using conditional form of type-casting ''as?'' instead of force ''as!''. |
| 44 | + |
| 45 | +**Good:** |
| 46 | +```swift |
| 47 | +let a = 12 as? Int64 |
| 48 | +// a being of Int64? type |
| 49 | +``` |
| 50 | + |
| 51 | +**Bad:** |
| 52 | +```swift |
| 53 | +let a = 12 as! Int64 |
| 54 | +// a being of Int64! type |
| 55 | +``` |
| 56 | + |
| 57 | +//Rationale:// Casting can fail, and handling the variable as a conditional can avoid the program from crashing. |
| 58 | + |
| 59 | + |
| 60 | +###Use Swift native types ===== |
| 61 | + |
| 62 | +Always use Swift's native types when available. Swift offers bridging to Objective-C so you can still use the full set of methods as needed. |
| 63 | + |
| 64 | +**Good:** |
| 65 | +```swift |
| 66 | +let width = 120.0 // Double |
| 67 | +let widthString = (width as NSNumber).stringValue // String |
| 68 | +``` |
| 69 | + |
| 70 | +**Bad:** |
| 71 | +```swift |
| 72 | +let width: NSNumber = 120.0 // NSNumber |
| 73 | +let widthString: NSString = width.stringValue // NSString |
| 74 | +``` |
| 75 | + |
| 76 | + |
| 77 | +###Start with action |
| 78 | + |
| 79 | +For methods that represent an action an object takes, start the name with the action. |
| 80 | + |
| 81 | +```swift |
| 82 | +<code c> |
| 83 | +func convertVariablesToFunctions() { ... } |
| 84 | +``` |
| 85 | + |
| 86 | +```swift |
| 87 | +<code c> |
| 88 | +func variablesToFunctions() { ... } |
| 89 | +``` |
| 90 | + |
| 91 | + |
| 92 | +### Keep methods small |
| 93 | + |
| 94 | +It is usually a good ideea to split large functions into smaller ones. Prefer small concise functions over smaller ones. |
| 95 | +Whenever you have a large function it can usually be split up into two more atomic functions. |
| 96 | + |
| 97 | + |
| 98 | +### Number of parameters |
| 99 | +Avoid creating methods with too many parameters. The ARM v6/v7/64 architectures allow for 3,5 and 7 parameters to be passed to a function via registers(fast storage), and following parameters are sent through RAM(slow storage). So remember, if you go beyond 3 parameters, you are not only making your method slower by using slower memory, you're also making it harder to read. |
| 100 | +[[https://www.mikeash.com/pyblog/friday-qa-2014-07-04-secrets-of-swifts-speed.html|Further Documentation]] |
| 101 | + |
| 102 | +**Good:** |
| 103 | +```swift |
| 104 | +func outputDetailsForFile(file: File) { ... } |
| 105 | +// File being an object that contains all those params |
| 106 | +``` |
| 107 | + |
| 108 | +**Bad:** |
| 109 | +```swift |
| 110 | +func outputDetailsForPath(path: String, fileSize: Int, extension: String, |
| 111 | + encoding enc: NSStringEncoding) { ... } |
| 112 | +``` |
0 commit comments