swift 小技巧进阶

时间:2022-04-20 02:46:32

guard 警卫

与if语句相同的是,guard也是基于一个表达式的布尔值去判断一段代码是否该被执行。与if语句不同的是,guard只有在条件不满足的时候才会执行这段代码。你可以把guard近似的看做是Assert,但是你可以优雅的退出而非崩溃。


 guard let x = x where x > 0 else {
// 变量不符合条件判断时,执行下面代码
return
}

使用guard语句问题:

  1. 是对你所期望的条件做检查,而非不符合你期望的。又是和assert很相似。如果条件不符合,guard的else语句就运行,从而退出这个函数。
  2. 如果通过了条件判断,可选类型的变量在guard语句被调用的范围内会被自动的拆包 - 这个例子中该范围是fooGuard函数内部。这是一个很重要,却有点奇怪的特性,但让guard语句十分实用。
  3. 对你所不期望的情况早做检查,使得你写的函数更易读,更易维护。


文件结构与访问控制

在swift中,一个类不再分为interface(.h)与implementation(.m)两个文件实现,直接在一个.swift文件里进行处理。好处就是我们只需管理一份文件,以往两头奔波修改的情况就得到解放了,也减少了头文件与实现文件不同步导致的错误。

这时我们会想到,那么我们如何来定义私有方法与属性呢,在OC中我们通过在class extension中定义私有属性,在.m文件定义私有方法。

而在Swift中,我们通过Access Control来进行控制。

properties, types, functions等能够进行版本控制的统称为实体。

Public:可以访问自己模块或应用中源文件里的任何实体,别人也可以访问引入该模块中源文件里的所有实体。通常情况下,某个接口或Framework是可以被任何人使用时,你可以将其设置为public级别。

Internal:可以访问自己模块或应用中源文件里的任何实体,但是别人不能访问该模块中源文件里的实体。通常情况下,某个接口或Framework作为内部结构使用时,你可以将其设置为internal级别。

Private:只能在当前源文件中使用的实体,称为私有实体。使用private级别,可以用作隐藏某些功能的实现细节

一个小技巧,如果我们有一系列的私有方法,我们可以把它们组织起来,放进一个extension里,这样就不需要每个方法都标记private,同时也便于管理组织代码:

// MARK: Private

private extension ViewController {

func privateFunction() {

}

}


协议(Protocols)

语法:

在Objective-C中我们这么声明Protocol:

@protocol SampleProtocol

- (void)someMethod;

@end

而在Swift中:

protocol SampleProtocol

{

func someMethod()

}

在Swift遵循协议:

class AnotherClass: SomeSuperClass, SampleProtocol

{

func someMethod() {}

}

那么之前Objective-C的protocol中,我们可以标志optional。那在Swift中呢?

遗憾的是,目前纯Swift的protocol还不支持optional。但根据苹果官方论坛的一位员工的回答,未来Swift是会支持的。


protocol和delegate是紧密联系的。那么我们在Swift中如何定义Delegate呢?

protocol MyDelegate : class {

}

class MyClass {

weak var delegate : MyDelegate?

}

注意到上面的protocol定义后面跟着的class。这意味着该protocol只能被class类型所遵守。

并且只有遵守了class protocol的delegate才能定义为weak。这是因为在Swift中,除了class能够遵守协议,枚举和结构同样能够遵守协议。而枚举和结构是值类型,不存在内存管理的问题。因此只需要class类型的变量声明为weak即可。

利用Swift的optional chaining,我们能够很方便的检查delegate是否为Nil,是否有实现某个方法:

以前我们要在Objective-C这样检查:

if(self.dataSource && [self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {

thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];

}

在Swift中,非常的优雅简洁。

if let thisSementTitle = dataSource?.titleFroSegmentAtIndex?(index){

}

新特性:

1.在Swift中,protocol变得更加强大,灵活:

2.class,enum,structure都可以遵守协议。

Extension也能遵守协议。利用它,我们不需要继承,也能够让系统的类也遵循我们的协议。

例如:

protocol myProtocol {

func hello() -> String

}

extension String:myProtocol{

func hello() -> String {

return"hello world!"

}

}

我们还能够用这个特性来组织我们的代码结构,如下面的代码所示,将UITableViewDataSource的实现移到了Extension。使代码更清晰。

// MARK: - UITableViewDataSource

extension MyViewcontroller: UITableViewDataSource {

// table view data source methods

}


类型转换     var  a : Int = 0 var b : CGFloat = CGFloat(a) 先写类型,在写()


计算属性,  感觉更像一个方法


swift 3.0 会移除下面这种风格,用swift 代替

for(int i = 1; i <= 5; i++)

{

NSLog(@"%d", i);

}

改写为:

for index in1...5 {

print(index)

}

for index in stride(from: 1, through: 5, by: 2) {

print(index)

}// through是包括5, by 是步长


类方法 声明

+ (UIColor*)blackColor

对应的swift版本

class func blackColor() -> UIColor//类方法, 通过 class func 关键词声明



给函数设置默认值

func configureCellWithModel(Model: model,color:UIColor)

而在Swift中,default parameter values的引入让我们能够这样修改我们的代码:

func configureCellWithModel(Model: model,color:UIColor = UIColor.whiteColor())



可变参数
可变参数用于接受零个或多个值(个数不确定),通过在变量类型名后面加入(...)的方式定义

例子:
// 函数实现
func arithmeticMean(numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}

// 函数调用
arithmeticMean(1,2,3,4,5)