iOS 代码规范

2021-10-14  本文已影响0人  我会回来的

iOS Swift 代码规范

编码格式

使用二元运算符(+, -,==, 或->)的前后都需要添加空格

let value = 1 + 2

在逗号后面加一个空格

let titleArray = [1, 2, 3, 4, 5]

方法的左大括号不要另起,并和方法名之间留有空格,注释空格

// function Define

func myFunction {

    // 处理

}

判断语句不用加括号

if typeValue == 1 {

    // 处理

}

尽量不使用self. 除非方法参数与属性同名

func setPerson(name: String, pAge: Int) {

    self.name = name

    age = pAge

}

在访问枚举类型时,使用更简洁的点语法

enum Direction {

    case north

    case south

    case east

    case west

}

let currentDirection = .west

添加有必要的注释,尽可能使用Xcode注释快捷键(⌘⌥/)

/// <#Description#>

///

/// - Parameters:

///  - tableView: <#tableView description#>

///  - section: <#section description#>

/// - Returns: <#return value description#>

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return dataList.count

}

使用 // MARK: -,按功能、协议、代理等分组

// MARK: - UITableViewDelegate

// MARK: - Action

// MARK: - Request

协议一致性:当对象要实现协议一致性时,推荐使用 extension 隔离协议中的方法集,这样让相关方法和协议集中在一起,方便归类和查找

// MARK: - UICollectionViewDelegate, UICollectionViewDataSource

extension XMHomeViewController: UICollectionViewDelegate, UICollectionViewDataSource {

    // 代理方法

}

// MARK: - HttpsRequest

extension XMHomeViewController {

    // 网络请求方法

}

当对外接口不兼容时,使用@available(iOS x.0, *) 标明接口适配的起始系统版本号

@available(iOS 8.0, *)

func myFunction() {

    //

}

命名规范

常量,变量,函数,方法的命名规则使用小驼峰规则,首字母小写,类型名使用大驼峰规则,首字母大写。

class MyClass: class {

    let myImageView: UIImageView

    let myName: String

}

当命名里出现缩写词时,缩写词要么全部大写,要么全部小写,以首字母大小写为准

let htmlString = "https://www.baidu.com"

let urlString:  URLString

let userID:  UserID

class HTMLModel {

    //

}

bool类型命名时,使用is作为前缀

var isMine: Bool = false

Swift中类别(类,结构体)在编译时会把模块设置为默认的命名空间,所以不用为了区分类别而添加前缀,比如XYHomeViewController,但是为了和引用的第三方库作区分,建议可以继续使用前缀,以作为规范化处理,结构更清晰。

懒加载用来细致地控制对象的生命周期,这对于想实现延迟加载视图的UIViewController特别有用

// MARK: - 懒加载

private lazy var tableView: UITableView = {

    let tableView = UITableView.init(frame: CGRect.zero, style: .plain)

    tableView.separatorStyle = .none

    tableView.rowHeight = UITableViewAutomaticDimension

    tableView.estimatedRowHeight = 200

    tableView.dataSource = self

    tableView.delegate = self

    tableView.register(UINib(nibName: homeListCell, bundle: nil), forCellReuseIdentifier: homeListCell)

    return tableView

}()

当函数的第一个参数构成整个语句的介词时(如,at, by, for, in, to, with 等),为第一个参数添加介词参数标签

func login(with username: String?, password: String?) {

    //

}

语法规范

可选类型拆包取值时,使用if let 判断

if let data = result.data {

    //

}

多个可选类型拆包取值时,将多个if let 判断合并

if let name = person.name, let age = person.age {

    //

}

尽量不要使用 as! 或 try!,对于可选类型Optional多使用as?,?? 可以给变量设置默认值

// 使用if let as?判断

if let name = person.name as? String {

    //

}

// 给name变量设置默认值

var name = person.name ?? ""

类型推断:推荐用紧凑方式写代码,让编辑器推断实例中常量和变量的类型。类型推断也适用于小型非空数组/字典。如有需要,请指定特定类型,例如:CGFloat或者Int16等。

// 推荐写法

let message = "Click the button"

let currentBounds = computeViewBounds()

var names = ["Mic", "Sam", "Christine"]

let maximumWidth: CGFloat = 106.5

// 不推荐写法

let message: String = "Click the button"

let currentBounds: CGRect = computeViewBounds()

var names: [String] = ["Mic", "Sam", "Christine"]

针对空数组和空字典的类型推断写法,推荐使用类型注释。此准则也意味着选择描述性名称比以前更加重要。

// 推荐写法

var names: [String] = []

var lookup: [String: Int] = [:]

// 不推荐写法

var names = [String]()

var lookup = [String: Int]()

常量定义,建议尽可能定义在类型里面,避免污染全局命名空间,如果是其他地方有可能复用的cell可以定义在类型外面

static let homeListCell = "HomeListCell"

class HomeListCell: UITableViewCell {

    static let kHomeCellHeight = 80.0

    //

}

当方法最后一个参数是Closure类型,调用时建议使用尾随闭包语法

UIView.animateWithDuration(1.0) {

    self.myView.alpha=0

}

最短路径规则:当编码遇到条件判断时,左边的距离是黄金路径或幸福路径,因为路径越短,速度越快。guard 就为此而生的。

func login(with username: String?, password: String?) throws -> LoginError {

  guard let username = username else {

    throw .noUsername

  }

  guard let password = password else {

    throw .noPassword

  }

  // 处理登录

}

循环遍历使用for-in表达式

// 循环

for _ in 0..<list.count {

  print("items")

}

// 遍历

for(index, person) in personList.enumerate() {

    print("\(person)is at position #\(index)")

}

// 间隔2位循环

for index in 0.stride(from: 0, to: items.count, by: 2) {

  print(index)

}

// 翻转

for index in (0...3).reversed() {

    print(index)

}

Swift4.2新特性

CaseIterable协议:定义的枚举遵循CaseIterable协议后,编译时Swift 会自动合成一个allCases属性,是包含枚举的所有case项的数组

enum NetState: CaseIterable {

    case wifi

    case hotWifi

    case mobile

    case none

}

for item in NetState.allCases {

    print(item)

}

warning 主要用于标记一些工作还没有完成或者需要完善,Xcode 会发出一个警告;#error 标记错误,Xcode 会发出一个编译错误这样你的代码就完全不能编译

#warning("列表刷新需要优化")

#if os(macOS)

#error("MyLibrary is not supported on macOS.")

#endif

新增 allSatisfy():一种检查序列中的所有元素是否满足条件的新方法

// 判断数组的所有元素是否全部大于80

let scores = [86, 88, 95, 92]

// 返回一个BOOL

let passed = scores.allSatisfy({ $0 > 80 })

print(passed)

// 输出:true

新增 last(where:) 和 lastIndex(where:) 方法来获取数组中满足条件的最后的元素和索引值

let a = [10, 20, 30, 40, 50, 30, 20]

// 获取满足条件的元素

print(a.last(where: { $0 > 30 }))  //50

// 获取满足条件的元素的索引

print(a.lastIndex(where: { $0 > 25 }))  //4

新增 random() 随机数方法来生成一个随机数, 只需提供一个随机数范围即可

// 随机数

let ranInt = Int.random(in: 0..<10)

let ranFloat = Float.random(in: 0..<10)

let a = [10, 20, 30, 40, 50, 30, 20]

// 对数组重新洗牌, 重新随机排序返回一个数组

let shuffled = a.shuffled()

// 获取数组中的一个随机元素,空数组返回nil

let random = a.randomElement()

新增 removeAll(where:) 方法,高效地执行根据条件删除操作

var names = ["John", "Michael", "Graham", "Andy", "Eric", "Andy"]

names.removeAll { $0.hasPrefix("Andy") }

print(names)

// 输出:["John", "Michael", "Graham", "Eric"]

Swift5新特性

ABI(Application Binary Interface)稳定:ABI定义了函数如何调用,数据如何在内存中呈现,元数据在哪里,以及如何访问等底层交互。之前的Swift版本中ABI还没稳定,所以每一个APP,都自己包含它Swift版本所对应的Swift Dynamic Library。ABI稳定之后,Swift动态库将包含在iOS操作系统里,它将兼容每一个Swift版本。

新增 @dynamicCallable 为Swift添加了一个新属性,允许使用一个简单的语法糖像调用函数一样调用命名类型,需要实现下面两个方法中的一个

func dynamicallyCall(withArguments args: [Int]) -> Double

func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double

// 定义方式

@dynamicCallable

struct RandomNumberGenerator {

    func dynamicallyCall(withArguments args: [Int]) -> Double {

        let numberOfZeroes = Double(args.first ?? 0)

        let maximum = pow(10, numberOfZeroes)

        return Double.random(in: 0...maximum)

    }

}

// 调用方式

let random = RandomNumberGenerator()

let num = random(2)

// random(2)等同于random.dynamicallyCall(withArguments: [2])

修改:定义一个带有(可变参数 => 数组参数)的枚举

enum X {

    case foo(bar: [Int])

}

func baz() -> X {

    return .foo(bar: [0, 1, 2, 3])

}

新增创建原始字符串的功能,以及创建多行字符串

let quote = "Alice: \"How long is forever?\" White Rabbit: \"Sometimes, just one second.\""

let rain = #"The "rain" in "Spain" falls mainly on the Spaniards."#

let multiline = #"""

    The answer to life,

    and everything is \#(answer).

    """#

Swift 5中无论有多少个嵌套的可选,最后返回值永远只是一个可选值,使用try?

// 类型: let messages: String?

let messages = try? user?.getMessages()

print(messages ?? "")

新增了一个函数 count(where:),可以获取数组中符合条件的元素的个数

let arr = [1, 28, 3, 40, 5, 6]

let count = arr.count(where: { $0 > 10 })

print(count)  // 2

在 Swift4.x 的版本中有两个函数 compactMap 和 mapValues

compactMap: 返回一个操作后得到的新的数组, 类似flatMap

mapValues: 对字典的value值执行操作, 返回改变value后的新的字典

Swift5.0 新增了一个函数 compactMapValues 返回一个对value操作后的新字典, 并且自动过滤不符合条件的键值对

let guys = [

    "Hudson": "30",

    "Clarke": "40",

    "Robinson": "50",

    "Hartis": "DNF"

]

let comMap = guys.compactMapValues({ Int($0) + 3 })

print(comMap)

// ["Clarke": 43, "Robinson": 53, "Hudson": 33]

转载 https://www.jianshu.com/p/7e6d18e91543

参考文献

https://blog.csdn.net/liushuo19920327/article/details/79121384

上一篇 下一篇

猜你喜欢

热点阅读