1. 利用嵌套类型,定义命名空间
public struct Map {
public struct Model {
public let size: Size
public let theme: Theme
public var terrain: [Position: Terrain.Model]
public var units: [Position: Unit.Model]
public buildings: [Position: Building.Model]
}
public enum Direction {
case up
case right
case down
case left
}
public struct Position {
public var x: Int
public var y: Int
}
public enum Size: String {
case small = "S"
case medium = "M"
case large = "L"
case extraLarge = "XL"
}
}
此处只是命名空间的冰山一角,可以查阅更多资料了解更多命名空间的知识点。
2. 使用@autoclosure
extension Dictionary {
mutating func value(for key: Key, orAdd valueClosure: @autoclosure () -> Value) -> Value {
if let value = self[key] {
return value
}
let value = valueClosure()
self[key] = value
return value
}
}
使用@autoclosure,可以让api更加的nice。在调用的时候,api更加的简洁。具体可以参考文章:Swift中@autoclosure。
3. 注释的风格
// 内部(internal)参数的注释
class Foo {
/**
* - parameter string: A string
*/
func bar(with string: String) {}
}
// 外部(external)参数的注释
class Foo {
/**
* - parameter string with: A string
*/
func bar(with string: String) {}
}
方法的注释,既可以对内部参数解释,也可对外部参数解释,不过务必保持统一。
4. 使用typealias减少方法签名的长度
public class PathFinder<Object: PathFinderObject> {
public typealias Map = Object.Map
public typealias Node = Map.Node
public typealias Path = PathFinderPath<Object>
public static func possiblePaths(for object: Object, at rootNode: Node, on map: Map) -> Path.Sequence {
return .init(object: object, rootNode: rootNode, map: map)
}
}
使用typealias定义类型,在方法定义的时候,可以有效减少方法名(方法签名)的长度。
5. 使用Wrap组件去实现Equatable
protocol AutoEquatable: Equatable {}
extension AutoEquatable {
static func ==(lhs: Self, rhs: self) -> Bool {
let lhsData = try! wrap(lhs) as Data
let rhsData = try! wrap(lhs) as Data
return lhsData == rhsData
}
}
在swift中,若要实现Equatable协议,需要重写static func ==(lhs, rhs) -> Bool
方法,这无疑增加了代码量,使用Wrap可以减少代码量。
6. 使用标准库中已经存在的类名
extension Command {
enum Error: Swift.Error {
case missin
case invalid(String)
}
}
如果一个名称已经被标准库占用,使用Swift.
作为前缀即可。
7. Using #function for UserDefaults key consistency
extension userDefaults {
var onboardingCompleted: Bool {
get { return bool(forKey: #function) }
set { set(newValue, forKey: #function) }
}
}
🗝 通常我们使用UserDefaults时候,都是通过字符串作为Key,这有可能会因为书写错误,导致存取时候出错,这类错误很难排查。我们可以给UserDefaults扩展计算属性,如上面的代码,key的值设置为#function,这是swift中的关键字,表示方法的签名,在这里表示"onboardingCompleted",这样就避免了书写错误。
8. 将函数和操作符作为必包传递
let array = [3, 9, 1, 4, 6, 2]
let sorted = array.sorted(by: <)
❤️ 在swift中,可以将函数function
&操作符operators
作为必包传递给函数参数,例如为一个数组排序时,可以使用上述代码,
9. 在不同的条件判断下,使用guard语句
// you can use the 'guard' statement to...
for string in strings {
guard shouldProcess(string) else {
continue
}
guard !shouldBreak(for: string) else {
break
}
guard !shouldReturn(for: string) else {
return
}
// throw an error
guard string.isValid else {
throw StringError.invalid(string)
}
// exit the program
guard !shouldExist(for: string) else {
exit(1)
}
}
guard不仅可以用于return,还能用于continue、break、throw等,合理使用guard可以有效避免代码多层嵌套。
10. 在switch语句中,避免使用default
enum State {
case loggedIn
case loggedOut
case onboarding
}
func handle(_ state: State) {
switch state {
case .loggedIn:
showMiainUI()
case .loggedOut:
showLoginUI()
// Compiler error: switch must be exhaustive
}
}
在swift中,使用enum的switch语法时,避免使用default是一个很好的实践。这样,它将会在新增一个case的时候,强制要求你更新逻辑。
网友评论