注:以下皆為翻譯,如有錯(cuò)誤或疏漏拣度,請(qǐng)指正。謝謝?
簡(jiǎn)介
SlideShare 版
Swift
官方 SlideShare Swift 代碼規(guī)范
這份規(guī)范是用于 swift 編寫 iOS8 及以上應(yīng)用蜂莉。
目錄
- Xcode Preferences
- Switch
- Properties
- Closures
- Identifiers
- Singleton
- Optionals
- Strings
- Enums
- Documentation
<a id="xcode-preferences"/>
Xcode Preferences
- 用“空格鍵”代替“Tab鍵”蜡娶,每個(gè) Tab 對(duì)應(yīng)4個(gè)空格(
Xcode->Preferences->Text Editing->Indentation
)
<a id=""/>
Switch
- switch 狀態(tài)應(yīng)該有每個(gè) case 狀態(tài),包括 default映穗。
var value = 2
var test: String?
switch value {
case 1:
test = "abc"
default:
test = "xyz"
}
- 如果你想要一個(gè)object 或 struct 的多個(gè)值窖张,創(chuàng)建一個(gè) tuple。如下:
struct TestValue {
enum Val {
case A
case B
}
var value: Val = .A
var detail: String = "Test"
}
var testValue = TestValue()
switch (testValue.value, testValue.detail) {
case (.A, "Test"):
println("This is printed")
default:
println("This is not printed")
}
- 如果你不希望走到 default 蚁滋,用 assert宿接。
var test = "Hello"
switch test {
case "Hello"
print("It prints")
case "World"
print("It doesn't")
default:
assert(false, "Useful message for developer")
}
<a id=""/>
Properties
- 如果你希望創(chuàng)建一個(gè)只讀計(jì)算屬性,可以不需要 get{}
var computedProp: String {
if someBool {
return "Hello"
}
}
- 如果你希望創(chuàng)建一個(gè)可讀寫計(jì)算屬性辕录,必須實(shí)現(xiàn) get{} set{}
var computedProp: String {
get {
if someBool {
return "Hello"
}
}
set {
println(newValue)
}
}
- 同樣的道理 willSet{} didSet{}
var property = 10 {
willSet {
println("willSet")
}
didSet {
println("didSet")
}
}
- willSet 和 didSet 可以用 newValue 和 oldValue
var property = 10 {
willSet {
if newValue == 10 {
println("It’s 10")
}
}
didSet {
if oldValue == 10 {
println("It was 10")
}
}
}
- 創(chuàng)建一個(gè)class常量用 static
class Test {
static let ConstantValue: String = "TestString"
}
<a id=""/>
Closures
- 閉包中不需要參數(shù)類型在參數(shù)列表里睦霎。另外,參數(shù)放在同一行走诞。
doSomethingWithCompletion() { param1 in
println("\(param1)")
}
- 閉包放在方法參數(shù)的最后面副女。
// Definition
func newMethod(input: Int, onComplete methodToRun: (input: Int) -> Void) {
// content
}
// Usage
newMethod(10) { param in
println("output: \(param)"")
}
- However, if there are 2 closures as the last parameters, do not use trailing closure syntax for the last one as this is ambiguous. Also, when creating a closure inline as a method parameter, put the parameter name on a new line and follow the following indentation rules:
- 如果有兩個(gè)閉包作為最后的參數(shù)......
testMethod(param: 2.5,
success: {
println("success")
},
failure: {
println("failure")
})
- Use trailing closure syntax if a closure is the only parameter:
- 如果閉包是僅有的參數(shù)......
array1.map { /* content */ }
- If declaring the type of a function or closure with no return type, specify this by using Void as the return type. Also, put a space before and after -> when declaring a closure type:
- 如果閉包返回類型為
空
,......
func takeClosure(aClosure: () -> Void) {
// content
}
- 如果 func 或 closure 沒有返回值,就不要寫返回
func noReturn() {
// content
}
- 如果閉包太大蚣旱,就不要在一行創(chuàng)建碑幅,重新創(chuàng)建一個(gè)local變量
func foo(something: () -> Void) {
something()
}
func doEverything() {
let doSomething = {
var x = 1
for 1...3 {
x++
}
println(x)
}
foo(doSomething)
}
<a id=""/>
Identifiers
- Only use self.<parameter name> if you need to, which is when you have a parameter of the same name as the instance variable, or in closures:
- 僅僅在必要的時(shí)候用 self.
class Test {
var a: (() -> Void)?
var b: Int = 3
func foo(a: () -> Void) {
self.a = a
}
func foo1() {
foo() {
println(self.b)
}
}
}
- 如果定義一個(gè)變量捐顷,冒號(hào)直接在變量后面衅金,冒號(hào)后接空格
static var testVar: String
- 定義字典類型凶朗,冒號(hào)前后各包含一個(gè)空格
var someDictionary: [String : Int]
- 定義常量時(shí)禁悠,首字母大寫,駝峰方式
class TestClass {
let ConstantValue = 3
}
- 用 struct 定義多個(gè)常量
struct Constants {
static let A = "A"
static let B = "B"
}
<a id=""/>
Singleton
- 用以下方式實(shí)現(xiàn)單例
class ClassA {
static let sharedInstance: ClassA = ClassA()
private init() {
// ...
}
}
Note: Xcode currently (6.0.1) does not indent properly in this case. Use the indentation specified above.
<a id="optionals"/>
Optionals
- When unwrapping optionals, rebind the optional to the same name, unless there is a reason not to. This example shows this, but in this case it should be done within the binding.
- 使用 optional 變量時(shí)魁衙,使用相同的名字重新關(guān)聯(lián)變量羡忘。
func possibleBike() -> Bike? {
// content
}
let bike = possibleBike()
if let bike = bike {
// content
}
<a id="strings"/>
Strings
- When appending to a string, always use the += operator.
- 用 += 拼接字符串
var newString = "Hello"
newString += " world!"
Note: do not concatenate user-facing strings as the ordering could change in different languages
<a id="enums"/>
Enums
- When using an enum, always prefer the shorthand syntax when possible. The shorthand syntax should be possible whenever the type does not need to be inferred from the assigned value. Note: there are certain bugs that don't allow them to be used everywhere they should be possible.
- 當(dāng)使用enum,記住用短語(yǔ)義么鹤。
enum TestEnum {
case A
case B
}
var theValue: TestEnum?
var shouldBeA = true
if shouldBeA {
theValue = .A
} else {
theValue = .B
}
- When declaring and setting a variable/constant of an enum type, do so in the following manner.
- 聲明一個(gè)
enum
變量或常量
var testValue: TestEnum = .A
<a id="documentation"/>
Documentation
- 單行方法注釋如下
/// This method does nothing
func foo() {
// content
}
- 多行注釋如下
/**
This method does something.
It's very useful.
*/
func foo2() {
// content
}
- 用 swift 標(biāo)準(zhǔn)的注釋方式以方便快速查看,用 Ctl+I 格式化代碼
Note: Make sure to test your documentation by checking it's Quick Documentation by option-clicking on the method name.
/**
This method has parameters and a return type.
- Parameter input: This is an input parameter.
- Returns: True if it worked; false otherwise.
*/
func foo3(input: String) -> Bool {
// content
}
Note: The following section refers to marks, which are Swift's version of #pragma mark in Objective-C to separate code. There are 2 types of marks: section marks and sub-section marks.
Section Marks:
// MARK: - Section Name
Sub-section Marks:
// MARK: Sub-section Name
- 用 marks 暗示新的代碼段
class Stuff {
// MARK: - Instance methods
func newMethod() {
// content
}
}
-
class/struct 應(yīng)該按照以下順序組織
- Section: Singleton - Section: Declared Types (Enums, Structs, etc.), Type Aliases - Section: Constants - Section: Class Properties - Section: Instance Properties - Sub-section: Stored - Sub-section: Computed - Section: Init/Deinit - Section: Class Methods - Sub-section: Public - Sub-section: Private - Section: Instance Methods - Sub-section: Public - Sub-section: Private - Section: Protocols - Sub-section: <Protocol Name>
當(dāng)一個(gè) class 實(shí)現(xiàn)一個(gè) protocol ,用擴(kuò)展的形式棋返,一個(gè)擴(kuò)展對(duì)應(yīng)一個(gè) protocol
// NewProtocol.swift //
protocol NewProtocol {
func reqMethod()
}
// Test.swift //
class Test {
// content
}
// MARK: - Protocols
// MARK: NewProtocol
extension Test: NewProtocol {
func reqMethod() {
// content
}
}
Cocoa
目錄
- Protocols
- UITableView/UICollectionView
- Strings
- NSNotification
- App Delegate
- Core Foundation
- View Controllers
- UIView
- Objective-C Interoperability
<a id="protocols"></a>
Protocols
- 重用 protocol 需要 reuse identifier.
protocol ReusableView {
static var ReuseIdentifier: String { get }
static var NibName: String { get }
}
<a id="uitableview"></a>
UITableView & UICollectionView
- 在UITableViewCell/UICollectionViewCell的子類中延都,創(chuàng)建一個(gè)只讀計(jì)算屬性作為cell 的 reuse identifier,用大寫開頭懊昨,因?yàn)樗莻€(gè)常量窄潭。
class TableViewCell: UITableViewCell, ReusableView {
static let ReuseIdentifier: String = "TableViewCellIdentifier"
static let NibName: String = "CustomTableViewCell"
}
原因: 注冊(cè)一個(gè)UITableView 或 UICollectionView的重用 cell , 你需要 nib 名稱和重用 identifier.
<a id="strings"></a>
Strings
- 將
國(guó)際化
字符串放在變量中。
// Localizable.strings //
// <App Section>
"user_facing_string_key" = "This is a user-facing string."
// Someting.swift //
var userFacing = NSLocalizedString("user_facing_string_key", comment: "")
<a id="nsnotification"></a>
NSNotification
- 用倒過來的域名加 notification name酵颁。
com.linkedin.slideshare.notification_name
- 創(chuàng)建一個(gè) struct 管理所有notification的常量名。
struct GlobalNotifications {
static let ABC = ""
}
- 創(chuàng)建 lazy notification 監(jiān)聽變量月帝。
private lazy var handleNotification: (NSNotification!) -> Void { [weak self] notification in
// Handle the notification
}
原因: This way you can define capture semantics for self and also use the identifier as the selector in the addObserver method (see below) instead of a string.確保編譯安全.
- 創(chuàng)建registerNotifications() 和 deregisterNotifications()躏惋。
func registerNotifications() {
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(self, selector: handleNotificationABC, name: GlobalNotifications.ABC, object: nil)
}
func deregisterNotifications() {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
<a id="app-delegate"></a>
App Delegate
- 將應(yīng)用初始化代碼抽象到一個(gè)單獨(dú)的類中。
class AppInitializer {
func onAppStart() {
// content
}
}
<a id="core-foundation"></a>
Core Foundation
- 用如下方法代替 CGRectMake 等.
var rect = CGRect(x: 10, y: 10, width: 45, height: 300)
- 創(chuàng)建初始化為0時(shí)應(yīng)該使用如下方法:
var zeroRect = CGRect.zeroRect
<a id="view-controllers"></a>
View Controllers
- 如果 controller 和一個(gè) storyboard 關(guān)聯(lián)嚷辅,創(chuàng)建一個(gè)類方法名為createInstance返回一個(gè)用 storyboard 創(chuàng)建的實(shí)例簿姨。
static func createInstance() -> MasterViewController {
return UIStoryboard.initialControllerFromStoryboard("Master") as! MasterViewController
}
Reasoning: 如果你不會(huì)創(chuàng)建當(dāng)前類的子類,則用static ,否則用 class func
- 如果你有以上描述的情形簸搞,但是需要初始化屬性扁位,可以創(chuàng)建designated/convenience initializer。
static func createInstanceWithId(id: Int) -> MasterViewController {
let masterViewController = createInstance()
masterViewController.id = id
return masterViewController
}
<a id="uiview"></a>
UIView
- 如果一個(gè)類繼承自一個(gè)有 xib 初始化的 uiview趁俊,創(chuàng)建一個(gè)方法createInstance 用法如上文 View Controllers 部分域仇。
class CustomView: UIView {
private static let NibName: String = "CustomView"
static func createInstance() -> CustomView {
return NSBundle.mainBundle().loadNibNamed(nibName, owner: nil, options: nil)[0] as! CustomView
}
}
<a id="objective-c-interoperability"></a>
Objective-C Interoperability
- 你需要一個(gè) bridging-header 文件。如果你的工程里面會(huì)用到 OC 文件寺擂。
// <Product-Name>-Bridging-Header.h
#import "SDWebImageHeader.h"
// SDWebImageHeader.h
#import <SDWebImage/UIImageView+WebCache.h>
#import <SDWebImage/UIImage+MultiFormat.h>
#import <SDWebImage/SDWebImagePrefetcher.h>