美文网首页
Swift的一些总结

Swift的一些总结

作者: lim2 | 来源:发表于2018-01-05 11:48 被阅读198次

为什么需要Optional?

我们在对某个对象操作时可能会返回错误的结果:比如我们将某个字符串转为Int型,执行下面的指令:

letage = response.toInt()

这response如果是用户输入的,可能会输入不确定的数值Do you konw?那么就会得到错误的结果,在OC中遇到类似情况我们怎么处理呢?我们有如下的值可以表示错误:

但是你必须从不同的接口中去选择相应的错误类型,并且要记住这些错误类型,并且如果你忘记了判断,那么编译器是不会提醒你的。为了解决这个问题,Swift中引入了Optional的概念,将这种可能是nil的值进行打包。它可以表示上述所有错误的类型,同时,如果我们使用Optional,就一定要对它进行拆包,使用!号,如果不拆包会造成编译器错误,这就在编译期杜绝了可能在运行时出的错误,如下所示:

Need Unwrap

也可以使用Optional Binding将判断是否有值和拆包结合在一起使用:if let


varneighbors = ["Alex","Anna","Madison","Dave"]letindex = findIndexOfString("Anna", neighbors)ifletindexValue = index {    println("Hello, \(neighbors[indexValue])")}else{    println("Must've moved away")}


当然我们还可进一步使用Optional Binding--Optional Chain:

Optional Chain Binding

在Optional Chain中,只要其中一个Optional的值是nil,那么整个Optional Chain都将是nil,并且不会再执行接下来的取值,如果不是nil则继续执行。这样让我们的代码更加简洁更加安全。

Swift中的Optional其实是个枚举:

enumOptional {caseNonecaseSome(T)}

Swift中的内存管理

在Swift中也用的是ARC,也容易出现循环引用,这时需要使用weak属性。需要注意的是

weak引用的类型是Optional的。

Binding该Optional Type将会产生一个强引用。

如果仅仅是判断即用if判断,则不会产生强引用。

例如:

iflettenant = apt.tenant {  tenant.buzzIn() }

但是有些时候我们同时需要weak,又同时需要非Optional的。那么该怎么办?我们需要unowned属性,它也是weak的。

classPerson{varcard: CreditCard?}classCreditCard{unownedletholder: Person    init(holder: Person) {        self.holder = holder  } }

这说明holder没持指向Person,但是holder离开了Person它就不存在了。unowned很像unsafe unretain

Swift中的初始化

在Swift的初始化中需要谨记:

所有的变量在使用前必须初始化

设定完自己所有的变量之后再调用Super的初始化方法

在下面这个初始化的例子中:

init wrong

这样在init方法中没有初始化完自己的hasTurbo变量就直接调用super方法是会在编译的时候报错的,Swift为什么要这么做呢?因为可能会出现如下的情况:

why init wrong

也就是说在父类的init方法中可能会调用filGasTank()这个方法,而这个方法被子类所覆盖了,所以这时候就可能发生意向不到的bug。

初始化方法的覆盖也可能会产生问题:

比如我们有这样一个Car的类:


classCar {    var paintColor: Color    func fillGasTank() {...}    init(color: Color) {        paintColor = color        fillGasTank()    }}classRaceCar: Car {    var hasTurbo: Bool    init(color: Color, turbo: Bool) {        hasTurbo = turbosuper.init(color: color)}    convenience init(color: Color) {self.init(color: color, turbo:true)}    convenience init() {self.init(color: Color(gray:0.4))} }classFormulaOne: RaceCar {    let minimumWeight =642// inherited from RaceCar/*init(color: Color, turbo: Bool) {

        hasTurbo = turbo

        super.init(color: color)

    }

    convenience init(color: Color) {

        self.init(color: color, turbo: true)

    }

    convenience init() {

        self.init(color: Color(gray: 0.4))

    }

    */}


上面注释的内容是从父类中继承过来的,如果我们在子类中调用convenience init(color: Color)这个方法的时候,想让turbo这个参数的默认值为false,这时候我们就需要覆盖掉父类的convenience init方法了。这时我们需要实现自己的designed initializer


classFormulaOne:RaceCar {    let minimumWeight =642init(color: Color) {        super.init(color: color, turbo:false)}// not inherited from RaceCar/*init(color: Color, turbo: Bool)

    convenience init()

    */}


这样以后被注释的内容就不会再被继承了。就会直接掉用子类的designed init方法了。

懒加载属性

如果我们的某个属性需要很大的性能消耗,那么我们希望在使用的时候再创建该类,那么我们不必像在OC中那样重写其get方法,我们只需要在变量声明的前面加上lazy关键字即可。

lazy var color:UIColor=UIColor.red

这样就可以声明了一个懒加载的属性了。

Closures 基本用法

Swift中Array的sort方法实现了Closure,我们来看下:

varclients = ["Pestov","Buenaventura","Sreeram","Babbage"]clients.sort({(a:String,b:String) -> Boolinreturna < b }) println(clients)// [Babbage, Buenaventura, Pestov, Sreeram]

这样就实现了数组中的元素排序。

但是基于Swift强大的类型推断功能,我们可以将其简化为:

clients.sort({ a, binreturna < b})

因为这个Closure是有返回值的,所以编译器可以再次推断,所以我们可以这样写

clients.sort({ a, bina < b })

编译器还可以推断出其参数值,所以,我们这里可以写成

clients.sort({$0<$1})

因为我们还有尾随闭包,所以我们可以进一步简化

clients.sort{$0<$1}

Functional Programming

我们有很多函数式编程的高阶函数可以供调用:

letresult = words.filter{$0.hasSuffix("gry")}.map{$0.uppercaseString}

这样我们就可以找到所有以gry结尾的单词,并且将其转化为大写字母。如果这时结果是

ANGRY

HUNGRY

我们还可以调用reduce方法将其和成一个字符串

letreducedResult = result.reduce("HULK"){"\($0) \($1)"}

这时结果如下:

HULK ANGRY HUNGRY

函数值

比高可以传递一个函数,例如:

numbers.map{        println($0)} numbers.map(println)// 可以将一个函数传递过去var indexes = NSMutableIndexSet()numbers.map{    indexes.addIndex($0)} numbers.map(indexes.addIndex)// 可以将一个Method传过去

闭包是一个ARC对象

我们可以声明一个Closure属性:

varonTempratureChange: (Int) -> Void = {}func logTemperatureDifferences(initial: Int) {varprev = initial    onTemperatureChange = { nextinprintln("Changed \(next - prev)°F")prev = next }

因为function也是closure,那么我们可以这样写:

funclogTemperatureDifferences(initial: Int){    var prev = initial    funclog(next: Int) {        println("Changed \(next - prev)°F")prev = next }    onTemperatureChange =log

闭包的循环引用问题

和OC中的Block一样,Swift中也会出现循环引用的问题,我们来看看怎样解决:

classTemperatureNotifier{varonChange: (Int) -> Void = {}varcurrentTemp =72init() {        onChange = { tempincurrentTemp = temp  }// error: requires explicit 'self' } }

如果出现上面的循环引用问题,编译器会直接报错的,所以我们可以用上文提到的unowned来解决。我们可以将init()方法用下面的来取代:

init() {    unownedletuSelf = self    onChange = { tempinuSelf.currentTemp = temp    }

但是这样写还会出现一个问题,就是如果别处有一份逻辑一样的代码,某个人不注意拷贝过来了忘记将self改成uSelf,或者这个方法很长,写到下面的是忘记了将self改成uSelf,那么就会出现内存泄漏的问题。为了解决这个问题Swift中提出了下面的优雅做法:

init() {onChange = {[unownedself] tempinself.currentTemp = temp } }

Pattern Matching

switch中可以有范围,字符串和数字,并且Enum中可以关联属性,比如:

// case中含有范围funcdescribe(value: Int){switchvalue {case0...4: println("a few")case5...12: println("a lot")default:        println("a ton")} }// case中enumTrainStatus {caseOnTimecaseDelayed(Int)}

使用的时候如下:

switchtrainStatus {case.OnTime:}  println("on time")case.Delayed(letminutes)                        :println("delayed by \(minutes) minutes")

我们可以对这个delay做各种各样的匹配:

switchtrainStatus {case.OnTime:    println("on time")case.Delayed(1):    println("nearly on time")case.Delayed(2...10):    println("almost on time, I swear")case.Delayed(_):    println("it'll get here when it's ready")

Pattern Compose

也就是说Pattern可以组合出现,一个Pattern中可以包含其它的Pattern,比如对上文的TrainStatus再做以Pattern Compose:

enumVacationStatus {caseTraveling(TrainStatus)caseRelaxing(daysLeft: Int)}switchvacationStatus{case.Traveling(.OnTime):    tweet("Train's on time! Can't wait to get there!")case.Traveling(.Delayed(1...15)):    tweet("Train is delayed.")case.Traveling(.Delayed(_)):    tweet("OMG when will this train ride end #railfail")default:  print("relaxing")

Type Pattern

Pattern不仅仅可以作用于Enum,还可以作用于动态的类型,如:Class

func tuneUp(car: Car) {switchcar {caseletformulaOneasFormulaOne:        formulaOne.enterPit()caseletraceCarasRaceCar:ifraceCar.hasTurbo { raceCar.tuneTurbo() }        fallthroughdefault:        car.checkOil()        car.pumpTires()} }

这样在多态中就会变得非常有用了。

Tuple Patterns

Tuple pattern有其极其强大的功能,其可以对tuple的各个数值做以类型匹配。

letcolor = (1.0, 1.0, 1.0, 1.0)switch color {case(0.0, 0.5...1.0,letblue, _):    println("Green and \(blue * 100)% blue")caselet(r, g, b, 1.0)wherer == g && g == b:    println("Opaque grey \(r * 100)%")

我们甚至可以对其中的各个数值做以相应的模式匹配。

Pattern Matching的应用PList校验

比如我们有下面的方法来校验Plist中的内容是否有效

func stateFromPlist(list: Dictionary)  -> State?stateFromPlist(["name":"California","population":38_040_000,"abbr":"CA"])

这时我们要对population的值做以限制,如果是字符串返回nil,如果是超过某个范围的时候返回nil,如果是abbr中字母的个数大于2时候我们也返回nil,利用tuple pattern matching的强大特性,我们可以这样去做:

func stateFromPlist(list: Dictionary)  -> State? {switch(list["name"], list["population"], list["abbr"]) {case(        .Some(letlistNameasNSString),        .Some(letpopasNSNumber),        .Some(letabbrasNSString)      ) where abbr.length ==2:returnState(name: listName,population: pop,abbr: abbr)default:returnnil    } }

这就利用了tuple和限制想结合的方式优雅的解决了这个问题。

相关文章

  • swift构造过程总结(一):默认构造器

    swift构造过程总结系列是通过阅读swift官方文档后自己的一些总结。阅读过官方文档的同学都知道,在swift构...

  • Swift Review总结一:从 Swift Style 开始

    Swift Review总结一:从 Swift Style 开始 Swift Review总结一:从 Swift ...

  • Swift-基础

    Swift 基础部分知识总结 突然想写下一些东西,做一些总结,或许只有不断的总结不断的思考才会不断成长,才会更好。...

  • Swift 结构体

    对 Swift 学习 的一些总结学习文献:Chris Eidhof. “Swift 进阶” 类与结构体的主要不同点...

  • Swift最新语法总结

    swift最新语法总结(函数) swift最新语法总结(枚举类型与结构体) swift最新语法总结(类的使用) s...

  • Swift简单使用(数组)

    最近巩固swift ,把一些基础的用法,总结下,希望帮到有需要的人

  • Swift的一些总结

    为什么需要Optional? 我们在对某个对象操作时可能会返回错误的结果:比如我们将某个字符串转为Int型,执行下...

  • 认识Swift系列1之基础语法

    这篇swift的目的不是为了详细讲解swift,而是将学习过程中的一些感受以CheckList的方式总结下来,方便...

  • Swift字符处理

    比起很多传统语言,Swift在字符处理方面显得更加简洁易用。本文会总结一些Swift在字符处理上的常用方法,持续更...

  • Swift 针对 SDK extension 的统一管理

    最近一直在写 Swift 代码,闲来总结下使用 Swift 的一些经验。在使用第三方 SDK 的时候,我们为了方便...

网友评论

      本文标题:Swift的一些总结

      本文链接:https://www.haomeiwen.com/subject/diijnxtx.html