Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

**Archived** Style guide & coding conventions for Swift projects

License

NotificationsYou must be signed in to change notification settings

github/swift-style-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 

A guide to our Swift style and conventions.

This is an attempt to encourage patterns that accomplish the following goals (inrough priority order):

  1. Increased rigor, and decreased likelihood of programmer error
  2. Increased clarity of intent
  3. Reduced verbosity
  4. Fewer debates about aesthetics

If you have suggestions, please see ourcontribution guidelines,then open a pull request. ⚡


Whitespace

  • Tabs, not spaces.
  • End files with a newline.
  • Make liberal use of vertical whitespace to divide code into logical chunks.
  • Don’t leave trailing whitespace.
    • Not even leading indentation on blank lines.

Preferlet-bindings overvar-bindings wherever possible

Uselet foo = … overvar foo = … wherever possible (and when in doubt). Only usevar if you absolutely have to (i.e. youknow that the value might change, e.g. when using theweak storage modifier).

Rationale: The intent and meaning of both keywords are clear, butlet-by-default results in safer and clearer code.

Alet-binding guarantees andclearly signals to the programmer that its value will never change. Subsequent code can thus make stronger assumptions about its usage.

It becomes easier to reason about code. Had you usedvar while still making the assumption that the value never changed, you would have to manually check that.

Accordingly, whenever you see avar identifier being used, assume that it will change and ask yourself why.

Return and break early

When you have to meet certain criteria to continue execution, try to exit early. So, instead of this:

if n.isNumber{    // Use n here}else{return}

use this:

guard n.isNumberelse{return}// Use n here

You can also do it withif statement, but usingguard is preferred, becauseguard statement withoutreturn,break orcontinue produces a compile-time error, so exit is guaranteed.

Avoid Using Force-Unwrapping of Optionals

If you have an identifierfoo of typeFooType? orFooType!, don't force-unwrap it to get to the underlying value (foo!) if possible.

Instead, prefer this:

iflet foo= foo{    // Use unwrapped `foo` value in here}else{    // If appropriate, handle the case where the optional is nil}

Alternatively, you might want to use Swift's Optional Chaining in some of these cases, such as:

// Call the function if `foo` is not nil. If `foo` is nil, ignore we ever tried to make the callfoo?.callSomethingIfFooIsNotNil()

Rationale: Explicitif let-binding of optionals results in safer code. Force unwrapping is more prone to lead to runtime crashes.

Avoid Using Implicitly Unwrapped Optionals

Where possible, uselet foo: FooType? instead oflet foo: FooType! iffoo may be nil (Note that in general,? can be used instead of!).

Rationale: Explicit optionals result in safer code. Implicitly unwrapped optionals have the potential of crashing at runtime.

Prefer implicit getters on read-only properties and subscripts

When possible, omit theget keyword on read-only computed properties andread-only subscripts.

So, write these:

varmyGreatProperty:Int{return4}subscript(index: Int)-> T{returnobjects[index]}

… not these:

varmyGreatProperty:Int{get{return4}}subscript(index: Int)-> T{get{returnobjects[index]}}

Rationale: The intent and meaning of the first version are clear, and results in less code.

Always specify access control explicitly for top-level definitions

Top-level functions, types, and variables should always have explicit access control specifiers:

publicvarwhoopsGlobalState:IntinternalstructTheFez{}privatefunc doTheThings(things:[Thing]){}

However, definitions within those can leave access control implicit, where appropriate:

internalstructTheFez{varowner:Person=Joshaber()}

Rationale: It's rarely appropriate for top-level definitions to be specificallyinternal, and being explicit ensures that careful thought goes into that decision. Within a definition, reusing the same access control specifier is just duplicative, and the default is usually reasonable.

When specifying a type, always associate the colon with the identifier

When specifying the type of an identifier, always put the colon immediatelyafter the identifier, followed by a space and then the type name.

classSmallBatchSustainableFairtrade:Coffee{...}lettimeToCoffee:NSTimeInterval=2func makeCoffee(type:CoffeeType)->Coffee{...}

Rationale: The type specifier is saying something about theidentifier soit should be positioned with it.

Also, when specifying the type of a dictionary, always put the colon immediatelyafter the key type, followed by a space and then the value type.

letcapitals:[Country:City]=[sweden: stockholm]

Only explicitly refer toself when required

When accessing properties or methods onself, leave the reference toself implicit by default:

privateclassHistory{varevents:[Event]func rewrite(){events=[]}}

Only include the explicit keyword when required by the language—for example, in a closure, or when parameter names conflict:

extensionHistory{init(events:[Event]){self.events= events}varwhenVictorious:()->(){return{self.rewrite()}}}

Rationale: This makes the capturing semantics ofself stand out more in closures, and avoids verbosity elsewhere.

Prefer structs over classes

Unless you require functionality that can only be provided by a class (like identity or deinitializers), implement a struct instead.

Note that inheritance is (by itself) usuallynot a good reason to use classes, because polymorphism can be provided by protocols, and implementation reuse can be provided through composition.

For example, this class hierarchy:

classVehicle{letnumberOfWheels:Intinit(numberOfWheels:Int){self.numberOfWheels= numberOfWheels}func maximumTotalTirePressure(pressurePerWheel:Float)->Float{return pressurePerWheel* Float(numberOfWheels)}}classBicycle:Vehicle{init(){        super.init(numberOfWheels:2)}}classCar:Vehicle{init(){        super.init(numberOfWheels:4)}}

could be refactored into these definitions:

protocolVehicle{varnumberOfWheels:Int{get}}func maximumTotalTirePressure(vehicle:Vehicle, pressurePerWheel:Float)->Float{return pressurePerWheel* Float(vehicle.numberOfWheels)}structBicycle:Vehicle{letnumberOfWheels=2}structCar:Vehicle{letnumberOfWheels=4}

Rationale: Value types are simpler, easier to reason about, and behave as expected with thelet keyword.

Make classesfinal by default

Classes should start asfinal, and only be changed to allow subclassing if a valid need for inheritance has been identified. Even in that case, as many definitions as possiblewithin the class should befinal as well, following the same rules.

Rationale: Composition is usually preferable to inheritance, and optingin to inheritance hopefully means that more thought will be put into the decision.

Omit type parameters where possible

Methods of parameterized types can omit type parameters on the receiving type when they’re identical to the receiver’s. For example:

struct Composite<T>{func compose(other:Composite<T>)->Composite<T>{returnComposite<T>(self, other)}}

could be rendered as:

struct Composite<T>{func compose(other:Composite)->Composite{returnComposite(self, other)}}

Rationale: Omitting redundant type parameters clarifies the intent, and makes it obvious by contrast when the returned type takes different type parameters.

Use whitespace around operator definitions

Use whitespace around operators when defining them. Instead of:

func<|(lhs:Int, rhs:Int)->Intfunc <|<<A>(lhs:A, rhs:A)->A

write:

func<|(lhs:Int, rhs:Int)->Intfunc <|<<A>(lhs:A, rhs:A)->A

Rationale: Operators consist of punctuation characters, which can make them difficult to read when immediately followed by the punctuation for a type or value parameter list. Adding whitespace separates the two more clearly.

Translations

About

**Archived** Style guide & coding conventions for Swift projects

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp