@Rookie
2022-06-22T07:29:43.000000Z
字数 5730
阅读 2315
iOS开发
enum Planet {case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune}struct Person {var mobileNo: String}
根据苹果接口设计指导准则,协议名称用来描述一些东西是什么的时候是名词,例如:Collection, WidgetFactory。若协议名称用来描述能力应该以 -ing, -able, 或 -ible 结尾,例如:Equatable, Resizing。
import SomeModulelet myClass = SomeModule.UsefulClass()
在定义委托方法时,第一个未命名参数应是委托数据源。
正确代码:
func namePickerView(_ namePickerView: NamePickerView, didSelectName name: String)func namePickerViewShouldReload(_ namePickerView: NamePickerView) -> Bool
错误代码:
func didSelectName(namePicker: NamePickerViewController, name: String)func namePickerShouldReload() -> Bool
泛型类参数应具有描述性,遵守“大骆驼命名法”。如果一个参数名没有具体的含义,可以使用传统单大写字符,如T, U, 或V等。
正确代码:
struct Stack<Element>{ ... }func writeTo <Target: OutputStream>(to Target: inout Target)func swap(_ a: inout T, _ b: inout T)
错误代码:
struct Stack<T>{ ... }func write<target: OutputStream> (to target: inout target)func swap<Thing>(_ a: inout Thing, _ b: inout Thing)
尽量使用类型推断以减少多余的冗余类型信息,例如:
正确的写法:
let currentLocation = Location()
错误的写法:
let currentLocation: Location = Location()
class BoardLocation {let row: Int, column: Intinit(row: Int, column: Int) {self.row = rowself.column = columnlet closure = {print(self.row)}}}
static。使用static修饰常量可以允许他们在被引用的时候不需要实例化类型。
struct PhysicsModel {static var speedOfLightInAVacuum = 299_792_458}class Spaceship {static let topSpeed = PhysicsModel.speedOfLightInAVacuumvar speed: Doublefunc fullSpeedAhead() {speed = Spaceship.topSpeed}}
正确代码:
class Example {var age: UInt32 {return arc4random()}}
错误代码:
class Example {var age: UInt32 {get {return arc4random()}}}
class Person {var age: Int {get {return Int(arc4random())}set {print("That's not your age.")}}}
Swift中单例很简单,Swift 的 runtime 会保证单例的创建并且采用线程安全的方式访问:
class ControversyManager {static let sharedInstance = ControversyManager()}
单例通常只需要访问"sharedInstance"的静态属性,除非你有不得已的原因去重命名它。注意,不要用静态函数或者全局函数去访问你的单例。
可以使用do/try/catch机制,避免使用try!和try?
?!用 [weak self] 和 guard let strongSelf = self else { return } 模式扩展生命周期。用 [weak self] 比 [unowned self] 更好。
正确代码:
resource.request().onComplete { [weak self] response inguard let strongSelf = self else { return }let model = strongSelf.updateModel(response)strongSelf.updateUI(model)}
错误代码:
// might crash if self is released before response returnsresource.request().onComplete { [unowned self] response inlet model = self.updateModel(response)self.updateUI(model)}
// deallocate could happen between updating the model and updating UIresource.request().onComplete { [weak self] response inlet model = self?.updateModel(response)self?.updateUI(model)}
Option+Command+/// MARK:分隔代码(类似于OC中的#pragma mark) 遵守Xcode内置的缩进格式
优先使用Swift原生类型,可以根据需要使用Objective-C提供的方法,因为Swift提供了到Objective-C的桥接 。
正确代码:
let width = 120.0 // Doublelet widthString = (width as NSNumber).stringValue // String
错误代码:
let width: NSNumber = 120.0 // NSNumberlet widthString: NSString=width.stringValue // NSString
当一个对象要实现协议一致性时,推荐使用 extension 隔离协议中的方法集,这样让相关方法和协议集中显示在一起,也简化了类支持一个协议和实现相关方法的流程。
正确代码:
class MyViewcontroller: UIViewController {// 方法}extension MyViewcontroller: UITableViewDataSource {// UITableViewDataSource 方法}extension MyViewcontroller: UIScrollViewDelegate {// UIScrollViewDelegate 方法}
错误代码:
class MyViewcontroller: UIViewController, UITableViewDataSource, UIScrollViewDelegate {// 所有的方法}
internal这样的默认的修饰符。也不需要在重写一个方法时添加访问修饰符。final修饰符
final class Circle: Shape {var x: Int, y: Intvar radius: Doublevar diameter: Double{get {returnradius * 2}set {radius=newValue/2}}init(x: Int, y: Int, radius: Double) {self.x = xself.y = yself.radius = radius}convenience init(x: Int, y: Int, diameter: Double) {self.init(x: x, y: y, radius: diameter/2)}func describe() -> String{return"I am a circle at\(centerString())with an area of\(computeArea())"}override func computeArea() -> Double{return M_PI * radius * radius}private func centerString()->String{return "(\(x),\(y))"}}
for _ in 0..<3 {print("Hello three times")}for(index, person) in attendeeList.enumerate() {print("\(person)is at position #\(index)")}for index in 0.stride(from: 0, to: items.count, by: 2) {print(index)}for index in (0...3).reverse() {print(index)}
错误代码:
var i=0while i<3 {print("Hello three times")i+=1}var i=0while i<3 {let person = attendeeList[i]print("\(person)is at position #\(i)")i+=1}
当编码遇到条件判断时,左边的距离是黄金路径或幸福路径,因为路径越短,速度越快。不要嵌套if循环,多个返回语句是可以的。guard 就为此而生的。
正确代码:
func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {guard let context = context else {throwFFTError.NoContext }guard let inputData = inputData else { throwFFTError.NoInputData }//计算frequenciesreturn frequencies}
错误代码:
func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {if let context = context {if let inputData = inputData {// 计算frequenciesreturn frequencies} else {throwFFTError.NoInputData}} else {throwFFTError.NoContext}}
当有多个条件需要用 guard 或 if let 解包,可用复合语句避免嵌套。
guard let number1=number1, number2=number2, number3=number3 else{fatalError("impossible")}// 处理number
//对空的数据和字典,使用类型注解var names: [String] = []var lookup: [String: Int] = [:]var deviceModels: [String]var employees: [Int:String]var faxNumber: Int?
自由函数不依附于任何类或类型,应该节制地使用。
正确代码:
let sorted = items.mergeSort() // 易发现性rocket.launch() // 可读性
错误代码:
let sorted = mergeSort(items)// 不易被发现launch(&rocket)
天然的自由函数:
let value = max(x,y,z) // another free function that feels natural
参考链接:
最详尽的 Swift 代码规范指南
Swift 3.0 编码规范
17条 Swift 最佳实践规范
一份比较通用的iOS代码规范,包括Objective-C和Swift
Swift 编码规范(中文)