Tag站长知识库:分享、传递知识使我们更快乐,更幸福,更和谐!

最近更新热门图文热门文章全站推荐Tag标签网站地图
您现在的位置:首页 > 程序开发 > Swift开发>>Swift可选链(Optional Chaining)

Swift可选链(Optional Chaining)

2019-06-17 17:21作者:佚名来源:易百教程浏览:33 评论:33

在可选的nil上查询,调用属性,下标和方法的过程叫作可选链。可选链接返回两个值 -

如果可选项包含值,则调用相关属性,方法和下标返回值。如果可选项包含nil值,则所有相关属性,方法和下标返回nil

由于对方法,属性和下标的多个查询组合在一起,因此对一个链的失败将影响整个链的结果为nil值。

可选链作为强制解包的替代方法

在带有?的可选值后指定可选链,在可选值返回某些值时调用属性,方法或下标。

可选链?访问方法,属性和下标可选链!强行展开
?在可选值之后放置调用属性,方法或下标!放在可选值之后调用属性,方法或下标来强制展开值
当可选项为nil时,优雅地失败当可选项为nil时,强制解包会触发运行时错误

使用 ! 进行可选链的程序

class ElectionPoll {   var candidate: Pollbooth?}lass Pollbooth {   var name = "MP"}let cand = ElectionPoll()let candname = cand.candidate!.name

当使用playground运行上述程序时,得到以下结果 -

fatal error: unexpectedly found nil while unwrapping an Optional value0 Swift 4 0x0000000103410b68llvm::sys::PrintStackTrace(__sFILE*) + 401 Swift 4 0x0000000103411054 SignalHandler(int) + 4522 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 263 libsystem_platform.dylib 0x000000000000000b _sigtramp + 18544929394 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 19767836365 Swift 4 0x0000000102a85c39llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 3296 Swift 4 0x0000000102d320b3llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,std::__1::vector<std::__1::basic_string, std::__1::allocator >,std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,char const* const*) + 15237 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift4::CompilerInstance&, std::__1::vector<std::__1::basic_string,std::__1::allocator >, std::__1::allocator<std::__1::basic_string,std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptionsconst&) + 10668 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,char const*, void*) + 52759 Swift 4 0x0000000102754a6d main + 167710 libdyld.dylib 0x00007fff8bb9e5c9 start + 111 libdyld.dylib 0x000000000000000c start + 1950751300Stack dump:0. Program arguments:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -target-cpu core2 -sdk/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk -module-name main/bin/sh: line 47: 15672 Done cat <<'SWIFT 4'import Foundation</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string

上述程序将“electionpoll”声明为类名,并包含candidate成员函数。 子类被声明为pollbooth,有一个名称为name成员函数,它被初始化为MP。 通过使用可选的!创建一个实例cand来初始化对超类的调用。 由于值未在基类中声明,因此存储nil值,从而通过强制解包过程返回致命错误。

使用 ? 的可选链程序

class ElectionPoll {   var candidate: Pollbooth?}class Pollbooth {   var name = "MP"}let cand = ElectionPoll()if let candname = cand.candidate?.name {   print("Candidate name is \(candname)")} else {   print("Candidate name cannot be retreived")}

当使用playground运行上述程序时,得到以下结果 -

Candidate name cannot be retreived

上述程序将electionpoll声明为类名,并使用candidate作为成员函数。 子类名称为pollbooth,使用name作为其成员函数,它被初始化为MP。 通过使用可选的?创建一个实例cand来初始化对超类的调用。 由于值未在其基类中声明nil,因此在else处理程序块存储并在控制台中打印。

为可选链和访问属性定义模型类

Swift 4语言提供了可选链的概念,将多个子类声明为模型类。 这个概念对于定义复杂模型和访问属性,方法和下标子属性非常有用。

class rectangle {   var print: circle?}class circle {   var area = [radius]()   var cprint: Int {      return area.count   }   subscript(i: Int) -> radius {      get {         return area[i]      }      set {         area[i] = newValue      }   }   func circleprint() {      print("The number of rooms is \(cprint)")   }   var rectarea: circumference?}class radius {   let radiusname: String   init(radiusname: String) { self.radiusname = radiusname }}class circumference {   var circumName: String?   var circumNumber: String?   var street: String?   func buildingIdentifier() -> String? {      if circumName != nil {         return circumName      } else if circumNumber != nil {         return circumNumber      } else {         return nil      }   }}let rectname = rectangle()if let rectarea = rectname.print?.cprint {   print("Area of rectangle is \(rectarea)")} else {   print("Rectangle Area is not specified")}

当使用playground运行上述程序时,得到以下结果 -

Rectangle Area is not specified

通过可选链接调用方法

class rectangle {   var print: circle?}class circle {   var area = [radius]()   var cprint: Int {      return area.count   }   subscript(i: Int) -> radius {      get {         return area[i]      }      set {         area[i] = newValue      }   }   func circleprint() {      print("Area of Circle is: \(cprint)")   }   var rectarea: circumference?}class radius {   let radiusname: String   init(radiusname: String) { self.radiusname = radiusname }}class circumference {   var circumName: String?   var circumNumber: String?   var circumarea: String?   func buildingIdentifier() -> String? {      if circumName != nil {         return circumName      } else if circumNumber != nil {         return circumNumber      } else {         return nil      }   }}let circname = rectangle()if circname.print?.circleprint() != nil {   print("Area of circle is specified)")} else {   print("Area of circle is not specified")}

当使用playground运行上述程序时,得到以下结果 -

Area of circle is not specified

通过创建名为circname的实例来调用circle()子类中声明的函数circleprint()。 如果函数包含某个值,则该函数将返回一个值,否则它将通过检查代码语句:if circname.print?.circleprint() != nil返回一些用户定义的打印消息。

通过可选链访问下标

可选链用于设置和检索下标值,以验证对下标的调用是否返回一个值。?放在下标大括号之前,以访问特定下标上的可选值。

程序1

class rectangle {   var print: circle?}class circle {   var area = [radius]()   var cprint: Int {      return area.count   }   subscript(i: Int) -> radius {      get {         return area[i]      }      set {         area[i] = newValue      }   }   func circleprint() {      print("The number of rooms is \(cprint)")   }   var rectarea: circumference?}class radius {   let radiusname: String   init(radiusname: String) { self.radiusname =  radiusname }}class circumference {   var circumName: String?   var circumNumber: String?   var circumarea: String?   func buildingIdentifier() -> String? {      if circumName != nil {         return circumName      } else if circumNumber != nil {         return circumNumber      } else {         return nil      }   }}let circname = rectangle()if let radiusName = circname.print?[0].radiusname {   print("The first room name is \(radiusName).")} else {   print("Radius is not specified.")}

当使用playground运行上述程序时,得到以下结果 -

Radius is not specified.

在上面的程序中,未指定成员函数radiusName的实例值。 因此,对函数的调用将仅返回其他部分,而返回必须是定义特定成员函数的值。

程序2

class rectangle {   var print: circle?}class circle {   var area = [radius]()   var cprint: Int {      return area.count   }   subscript(i: Int) -> radius {      get {         return area[i]      }      set {         area[i] = newValue      }   }   func circleprint() {      print("The number of rooms is \(cprint)")   }   var rectarea: circumference?}class radius {   let radiusname: String   init(radiusname: String) { self.radiusname = radiusname }}class circumference {   var circumName: String?   var circumNumber: String?   var circumarea: String?   func buildingIdentifier() -> String? {      if circumName != nil {         return circumName      } else if circumNumber != nil {         return circumNumber      } else {         return nil      }   }}let circname = rectangle()circname.print?[0] = radius(radiusname: "Diameter")let printing = circle()printing.area.append(radius(radiusname: "Units"))printing.area.append(radius(radiusname: "Meter"))circname.print = printingif let radiusName = circname.print?[0].radiusname {   print("Radius is measured in \(radiusName).")} else {   print("Radius is not specified.")}

当使用playground运行上述程序时,得到以下结果 -

Radius is measured in Units.

在上面的程序中,指定了成员函数radiusName的实例值。 因此,对函数的程序调用将会返回一个值。

访问可选类型的下标

class rectangle {   var print: circle?}class circle {   var area = [radius]()   var cprint: Int {      return area.count   }   subscript(i: Int) -> radius {      get {         return area[i]      }      set {         area[i] = newValue      }   }   func circleprint() {      print("The number of rooms is \(cprint)")   }   var rectarea: circumference?}class radius {   let radiusname: String   init(radiusname: String) { self.radiusname = radiusname }}class circumference {   var circumName: String?   var circumNumber: String?   var circumarea: String?   func buildingIdentifier() -> String? {      if circumName != nil {         return circumName      } else if circumNumber != nil {         return circumNumber      } else {         return nil      }   }}let circname = rectangle()circname.print?[0] = radius(radiusname: "Diameter")let printing = circle()printing.area.append(radius(radiusname: "Units"))printing.area.append(radius(radiusname: "Meter"))circname.print = printingvar area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]area["Radius"]?[1] = 78area["Circle"]?[1]--print(area["Radius"]?[0])print(area["Radius"]?[1])print(area["Radius"]?[2])print(area["Radius"]?[3])print(area["Circle"]?[0])print(area["Circle"]?[1])print(area["Circle"]?[2])

当使用playground运行上述程序时,得到以下结果 -

Optional(35)Optional(78)Optional(78)Optional(101)Optional(90)Optional(44)Optional(56)

可以通过引用下标值来访问下标的可选值。 它可以通过下标[0],下标[1]等来访问。“半径”的默认下标值首先分配为[35,45,78,101]和 Circle 为:[90,45,56]。 然后将下标值更改Radius [0]78,并将Circle[1]更改为45

链的多级链接

多个子类也可以通过可选链与其超类方法,属性和下标链接。

可选的多个链可以链接 -

如果检索类型不是可选的,则可选链接将返回可选值。 例如,如果String通过可选链它将返回String?值。

class rectangle {   var print: circle?}class circle {   var area = [radius]()   var cprint: Int {      return area.count   }   subscript(i: Int) -> radius {      get {         return area[i]      }      set {         area[i] = newValue      }   }   func circleprint() {      print("The number of rooms is \(cprint)")   }   var rectarea: circumference?}class radius {   let radiusname: String   init(radiusname: String) { self.radiusname = radiusname }}class circumference {   var circumName: String?   var circumNumber: String?   var circumarea: String?   func buildingIdentifier() -> String? {      if circumName != nil {         return circumName      } else if circumNumber != nil {         return circumNumber      } else {         return nil      }   }}let circname = rectangle()if let radiusName = circname.print?[0].radiusname {   print("The first room name is \(radiusName).")} else {   print("Radius is not specified.")}

当使用playground运行上述程序时,得到以下结果 -

Radius is not specified.

在上面的程序中,未指定成员函数radiusName的实例值。 因此,对函数的程序调用将仅返回其他部分,而返回必须定义特定成员函数的值。

如果检索类型已经是可选的,则可选链接也将返回可选值。 例如,如果String?通过可选链访问它会返回String?值。

class rectangle {   var print: circle?}class circle {   var area = [radius]()   var cprint: Int {      return area.count   }   subscript(i: Int) -> radius {      get {         return area[i]      }      set {         area[i] = newValue      }   }   func circleprint() {      print("The number of rooms is \(cprint)")   }   var rectarea: circumference?}class radius {   let radiusname: String   init(radiusname: String) { self.radiusname = radiusname }}class circumference {   var circumName: String?   var circumNumber: String?   var circumarea: String?   func buildingIdentifier() -> String? {      if circumName != nil {         return circumName      } else if circumNumber != nil {         return circumNumber      } else {         return nil      }   }}let circname = rectangle()circname.print?[0] = radius(radiusname: "Diameter")let printing = circle()printing.area.append(radius(radiusname: "Units"))printing.area.append(radius(radiusname: "Meter"))circname.print = printingif let radiusName = circname.print?[0].radiusname {   print("Radius is measured in \(radiusName).")} else {   print("Radius is not specified.")}

当使用playground运行上述程序时,得到以下结果 -

Radius is measured in Units.

在上面的程序中,指定了成员函数radiusName的实例值。 因此,对函数的程序调用将会返回一个值。

使用可选返回值链方法

可选链也用于访问子类定义的方法。

class rectangle {   var print: circle?}class circle {   var area = [radius]()   var cprint: Int {      return area.count   }   subscript(i: Int) -> radius {      get {         return area[i]      }      set {         area[i] = newValue      }   }   func circleprint() {      print("Area of Circle is: \(cprint)")   }   var rectarea: circumference?}class radius {   let radiusname: String   init(radiusname: String) { self.radiusname = radiusname }}class circumference {   var circumName: String?   var circumNumber: String?   var circumarea: String?   func buildingIdentifier() -> String? {      if circumName != nil {         return circumName      } else if circumNumber != nil {         return circumNumber      } else {         return nil      }   }}let circname = rectangle()if circname.print?.circleprint() != nil {   print("Area of circle is specified)")} else {   print("Area of circle is not specified")}

当使用playground运行上述程序时,得到以下结果 -

Area of circle is not specified

Tags: 责任编辑:Tag站长知识库
下一篇:Swift类型转换
顶一下(33)
87.08%

精彩信息

     

精彩信息

     

精彩信息