Swift编程规范之 Coding Style
Coding Style 1 General
// PREFERRED
let stringOfInts = [1,2,3].flatMap { String($0) }
// ["1","2","3"]
// NOT PREFERRED
var stringOfInts: [String] = []
for integer in [1,3] {
stringOfInts.append(String(integer))
}
// PREFERRED
let evenNumbers = [4,8,15,16,23,42].filter { $0 % 2 == 0 }
// [4,8,16,42]
// NOT PREFERRED
var evenNumbers: [Int] = []
for integer in [4,42] {
if integer % 2 == 0 {
evenNumbers(integer)
}
}
func pirateName() -> (firstName: String,lastName: String) {
return ("Guybrush","Threepwood")
}
let name = pirateName()
let firstName = name.firstName
let lastName = name.lastName
myFunctionWithClosure() { [weak self] (error) -> Void in
// you can do this
self?.doSomething()
// or you can do this
guard let strongSelf = self else {
return
}
strongSelf.doSomething()
}
// PREFERRED
if x == y {
/* ... */
}
// NOT PREFERRED
if (x == y) {
/* ... */
}
// PREFERRED
imageView.setImageWithURL(url,type: .person)
// NOT PREFERRED
imageView.setImageWithURL(url,type: AsyncImageView.Type.person)
// PREFERRED
imageView.backgroundColor = UIColor.whiteColor()
// NOT PREFERRED
imageView.backgroundColor = .whiteColor()
if someBoolean {
// do something
} else {
// do something else
}
do {
let fileContents = try readFile("filename.txt")
} catch {
print(error)
}
2 Access Modifiers
// PREFERRED
private static let kMyPrivateNumber: Int
// NOT PREFERRED
static private let kMyPrivateNumber: Int
// PREFERRED
public class Pirate {
/* ... */
}
// NOT PREFERRED
public
class Pirate {
/* ... */
}
/** This variable defines the pirate's name. - warning: Not `private` for `@testable`. */
let pirateName = "LeChuck"
3 Custom Operators:自定义操作符尽可能地选用命名函数来代替自定义操作符。如果你打算引入一个自定义的操作符,那么一定要有非常充分的理由来说明为啥要讲一个新的操作符引入到全局作用域,而不是使用其他一些可替代的方式。你也可以选择去复写一些现有的操作符,譬如==来适应一些新的类型,不过要保证你添加的用法一定要与语义相符。譬如== 应该只能用于表示相等性测试并且返回一个布尔值。 4 Switch Statements and enums
enum Problem {
case attitude
case hair
case hunger(hungerLevel: Int)
}
func handleProblem(problem: Problem) {
switch problem {
case .attitude:
print("At least I don't have a hair problem.")
case .hair:
print("Your barber didn't know when to stop.")
case .hunger(let hungerLevel):
print("The hunger level is (hungerLevel).")
}
}
func handleDigit(digit: Int) throws {
case 0,1,3,4,5,6,7,9:
print("Yes,(digit) is a digit!")
default:
throw Error(message: "The given number was not a digit.")
}
5 Optionals
The only time you should be using implicitly unwrapped optionals is withs. In every other case,it is better to use a non-optional or regular optional variable. Yes,there are cases in which you can probably “guarantee” that the variable will never be nil when used,but it is better to be safe and consistent.
// PREFERERED
if someOptional != nil {
// do something
}
// NOT PREFERRED
if let _ = someOptional {
// do something
}
// PREFERRED
weak var parentViewController: UIViewController?
// NOT PREFERRED
weak var parentViewController: UIViewController!
unowned var parentViewController: UIViewController
guard let myVariable = myVariable else {
return
}
6 Protocols在实现协议的时候,大体上有两种代码组织方式: 使用 // MARK: 来注释你的专门用于实现协议中规定的方法 在你的类或者结构体实现之外使用一个扩展来存放实现代码,不过要保证在一个源文件中 不过需要注意的是,如果你是使用了Extension方式,那么定义在Extension中的方法是无法被子类复写的,这样可能会无法进行测试。 7 Properties
var computedProperty: String {
if someBool {
return "I'm a mighty pirate!"
}
return "I'm selling these fine leather jackets."
}
var computedProperty: String {
get {
if someBool {
return "I'm a mighty pirate!"
}
return "I'm selling these fine leather jackets."
}
set {
computedProperty = newValue
}
willSet {
print("will set to (newValue)")
}
didSet {
print("did set from (oldValue) to (newValue)")
}
}
class MyTableViewCell: UITableViewCell {
static let kReuseIdentifier = String(MyTableViewCell)
static let kCellHeight: CGFloat = 80.0
}
class PirateManager {
static let sharedInstance = PirateManager()
/* ... */
}
8 Closures:闭包
// omitting the type
doSomethingWithClosure() { response in
print(response)
}
// explicit type
doSomethingWithClosure() { response: NSURLResponse in
print(response)
}
// using shorthand in a map statement
[1,3].flatMap { String($0) }
// parentheses due to capture list
doSomethingWithClosure() { [weak self] (response: NSURLResponse) in
self?.handleResponse(response)
}
// parentheses due to return type
doSomethingWithClosure() { (response: NSURLResponse) -> String in
return String(response)
}
let completionBlock: (success: Bool) -> Void = {
print("Success? (success)")
}
let completionBlock: () -> Void = {
print("Completed!")
}
let completionBlock: (() -> Void)? = nil
Keep parameter names on same line as the opening brace for closures when possible without too much horizontal overflow (i.e. ensure lines are less than 160 characters).
// trailing closure
doSomething(1.0) { parameter1 in
print("Parameter 1 is (parameter1)")
}
// no trailing closure
doSomething(1.0,success: { parameter1 in
print("Success with (parameter1)")
},failure: { parameter1 in
print("Failure with (parameter1)")
})
9 Arrays
10 Error Handling假设某个函数 myFunction 需要去返回一个String类型,不过有可能会在某个点抛出异常,一般来说会将该函数的返回值设置为String?: Example: func readFile(withFilename filename: String) -> String? {
guard let file = openFile(filename) else {
return nil
}
let fileContents = file.read()
file.close()
return fileContents
}
func printSomeFile() {
let filename = "somefile.txt"
guard let fileContents = readFile(filename) else {
print("Unable to open file (filename).")
return
}
print(fileContents)
}
不过作为异常处理的角度,我们应该使用Swift的try-catch表达式,这样能显式地知道错误点: struct Error: ErrorType {
public let file: StaticString
public let function: StaticString
public let line: UInt
public let message: String
public init(message: String,file: StaticString = #file,function: StaticString = #function,line: UInt = #line) {
self.file = file
self.function = function
self.line = line
self.message = message
}
}
Example usage: func readFile(withFilename filename: String) throws -> String {
guard let file = openFile(filename) else {
throw Error(message: "Unable to open file named (filename).")
}
let fileContents = file.read()
file.close()
return fileContents
}
func printSomeFile() {
do {
let fileContents = try readFile(filename)
print(fileContents)
} catch {
print(error)
}
}
总而言之,如果某个函数可能会出错,并且出错的原因不能显式地观测到,那么应该优先抛出异常而不是使用一个Optional作为返回值。 11 Using guard Statements
// PREFERRED
func eatDoughnut(atIndex index: Int) {
guard index >= 0 && index < doughnuts else {
// return early because the index is out of bounds
return
}
let doughnut = doughnuts[index]
eat(doughnut)
}
// NOT PREFERRED
func eatDoughnuts(atIndex index: Int) {
if index >= 0 && index < donuts.count {
let doughnut = doughnuts[index]
eat(doughnut)
}
}
// PREFERRED
guard let monkeyIsland = monkeyIsland else {
return
}
bookVacation(onIsland: monkeyIsland)
bragAboutVacation(onIsland: monkeyIsland)
// NOT PREFERRED
if let monkeyIsland = monkeyIsland {
bookVacation(onIsland: monkeyIsland)
bragAboutVacation(onIsland: monkeyIsland)
}
// EVEN LESS PREFERRED
if monkeyIsland == nil {
return
}
bookVacation(onIsland: monkeyIsland!)
bragAboutVacation(onIsland: monkeyIsland!)
// an `if` statement is readable here
if operationFailed {
return
}
// a `guard` statement is readable here
guard isSuccessful else {
return
}
// double negative logic like this can get hard to read - i.e. don't do this
guard !operationFailed else {
return
}
// PREFERRED
if isFriendly {
print("Hello,nice to meet you!")
} else {
print("You have the manners of a beggar.")
}
// NOT PREFERRED
guard isFriendly else {
print("You have the manners of a beggar.")
return
}
print("Hello,nice to meet you!")
if let monkeyIsland = monkeyIsland {
bookVacation(onIsland: monkeyIsland)
}
if let woodchuck = woodchuck where canChuckWood(woodchuck) {
woodchuck.chuckWood()
}
// combined because we just return
guard let thingOne = thingOne,let thingTwo = thingTwo,let thingThree = thingThree else {
return
}
// separate statements because we handle a specific error in each case
guard let thingOne = thingOne else {
throw Error(message: "Unwrapping thingOne failed.")
}
guard let thingTwo = thingTwo else {
throw Error(message: "Unwrapping thingTwo failed.")
}
guard let thingThree = thingThree else {
throw Error(message: "Unwrapping thingThree failed.")
}
// PREFERRED
guard let thingOne = thingOne else {
return
}
// NOT PREFERRED
guard let thingOne = thingOne else { return }
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |