美文网首页
Swift 基础(0) - 协议、枚举 、异常

Swift 基础(0) - 协议、枚举 、异常

作者: 静持大师 | 来源:发表于2017-03-26 20:56 被阅读33次

面向协议

  • 面向对象的问题: 不能实现多继承,且会导致继承关系变得复杂
  • 面向协议的事例:
protocol SportProtocol {
    var hot: Double  {get set} // {get set}表示可读可写
    
    func playFootBall()
    @objc optional func playBasketBall() // 前面的 @objc optional 表示方法是可选的
}

// 在协议中, 属性/方法可以在 extension 中默认实现
extension SportProtocol {
    var price: Double { // 此时属性只读, 想要修改, 必须覆盖
        return 100.0
    }
    
    func playFootBall() {
        print("T足球")
    }
}
  • 实现统一加载 nib的 协议
import Foundation
import UIKit

protocol NibLoadProtocol {
    
}

// where Self: UIView 表示调动的必须是 UIView 及其子类
extension NibLoadProtocol where Self: UIView {
    // 协议中 static 表示类方法
    static func loadFromNib() -> Self {
        return Bundle.main.loadNibNamed("\(self)", owner: nil, options: nil)?.first as! Self
    }
}

枚举

  • 枚举的语法,enum开头,每一行成员的定义使用case关键字开头,一行可以定义多个关键字
enum CompassPoint {
    case North
    case South
    case East
    case West
}
 
enum CompassPoint {
    case North, South, East, West
}

上例中North,South,East,West的值并不等于0,1,2,3,而是他们本身就是自己的值,且该值的类型就是CompassPoint
var directionToHead = CompassPoint.West 
// directionToHead是一个CompassPoint类型,可以被赋值为该类型的其他值
// 当设置directionToHead的值时,他的类型是已知的,因此可以省略East的类型
directionToHead = .East
  • 使用switch分开枚举的值,以进行的不同的操作。switch内的case必须包含枚举的所有分支,否则编译出错。当然,列举所有枚举值不太方便时,可以使用default
directionToHead = .South
switch directionToHead {
case .North:
    println("Lots of planets have a north")
case .South:
    println("Watch out for penguins")
case .East:
    println("Where the sun rises")
case .West:
    println("Where the skies are blue")
}
  • 枚举的元素可以是结合值(associated value),下面通过一个可以存储一维条形码(由3个整数组成)和二维条形码(由字符串组成)的枚举条形码实例来说明
enum Barcode {
    case UPCA(Int, Int, Int)
    case QRCode(String)
}
// 定义一个变量。该变量即可被赋值为3个整数,又可被赋值为一个字符串,但都是Barcode类型的枚举值
var productBarcode = Barcode.UPCA(8, 85909_51226, 3)
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
 
// 使用switch时,case内可区分条形码种类,可使用变量或常量获得结合值
switch productBarcode {
case .UPCA(let numberSystem, let identifier, let check):
    println("UPC-A with value of \(numberSystem), \(identifier), \(check).")
case .QRCode(let productCode):
    println("QR code with value of \(productCode).")
}
// 打印 "QR code with value of ABCDEFGHIJKLMNOP."

*在case内部,如果其类型都为let或var,则该关键字可提前到case和枚举类型中间,如:
case let .UPCA(numberSystem, identifier, check):
  • 原始值类型的枚举在枚举名后紧跟数据类型,其枚举的成员在定义时已经赋予了初始值,且不能改变,与结合值类型的枚举相比,结合值是在将枚举值赋予一个变量时,才设置了那个枚举的值。
//原始值枚举的类型紧跟枚举名后,其成员的原始值的数据类型都是这个指定的类型
enum ASCIIControlCharacter: Character {
    case Tab = "\t"
    case LineFeed = "\n"
    case CarriageReturn = "\r"
}
//Int类型的原始值枚举成员的原始值是递增的,比如Venus的值是2,Earth的值是3
enum Planet: Int {
    case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
//可以通过toRaw方法获得枚举成员的原始值
let earthsOrder = Planet.Earth.toRaw()
// earthsOrder 的值是 3,数据类型是Int
 
//可以通过fromRaw方法获得原始值对应的枚举成员
let possiblePlanet = Planet.fromRaw(7)
// possiblePlanet 的数据类型 Planet? 值是 Planet.Uranus
 
//因为fromRaw的原始值可能没有对应的枚举成员,所以返回的类型是一个可选变量值
let positionToFind = 9
if let somePlanet = Planet.fromRaw(positionToFind) {
    switch somePlanet {
    case .Earth:
        println("Mostly harmless")
    default:
        println("Not a safe place for humans")
    }
} else {
    println("There isn't a planet at position \(positionToFind)")
}
// 枚举定义中没有原始值为9的成员,所以打印 "There isn't a planet at position 9"

枚举函数

//枚举函数
enum mobileLanguageFun{
     case IOS (String, String)
     case Android (String)
     //定义枚举函数
     var description: String{
         switch self {
             case  mobileLanguageFun.IOS(let language1, let language2):
                 return "language1 = \(language1), language2 = \(language2)"
                 
             case mobileLanguageFun.Android(let temp):
                 return temp
             default:
                 return ("NO")
         }
 
     }
 }
 
 var myMobile: mobileLanguageFun = mobileLanguageFun.IOS("objc", "swift")
 println(myMobile.description)  //language1 = objc, language2 = swift

错误处理与异常抛出

主动退出程序的几种情况

  • Fatal Errors(致命的错误)
    • 使用fatalError()函数可以立即终止你的应用程序,在fatalError()中可以给出终止信息。使用fatalError()函数,会毫无条件的终止你的应用程序,用起来也是比较简单的,就是一个函数的调用。
fatalError("致命错误,调用我程序终止")
  • Assertions(断言)
    • 在断言中的提示条件是可选的。断言会在Debug模式下起作用,但是在Release版本中就会被忽略。
// @param: condition, 为true时,断言不执行,相应的断言信息不打印。为false时,断言执行,并且打印相应的断言信息。
assert(<#T##condition: Bool##Bool#>, <#T##message: String##String#>)
  • 先决条件(Preconditions)
    • Preconditions的用法和断言一样,不过有一点需要主要,Preconditions在debug和release模式下都会被执行,除非使用–Ounchecked进行编译。
precondition(<#T##condition: Bool##Bool#>, <#T##message: String##String#>)

Swift中的错误处理

  • 在Swift中,如果你要定义你自己的错误类型,你只需要实现ErrorType协议即可。声明完错误类型后,就可以在处理错误抛出异常时使用自定义的错误类型了。

1.使用枚举创建错误类型

  • 1.1遵循ErrorType协议,自定义错误类型。下方定义了一个错误类型枚举,该枚举遵循了ErrorType协议,在接下来的代码中我们将会使用这个MyCustomErrorType枚举
// 定义错误类型
enum MyErrorType: ErrorType {
    case ErrorReason1
    case ErrorReason2
    case ErrorReason3
}
  • 1.2在我们的函数定义时可以使用throws关键字,以及在函数中使用throw关键字对错误进行抛出,抛出的错误类型就可以使用上面我们自己定义的错误类型。
func throwError() throws {
        let test: Int? = nil
        
        guard test != nil else {
            throw MyErrorType.ErrorReason2
        }
    }
  • 1.3上面函数的功能是对错误进行抛出,接下来就该使用do-catch来处理抛出的错误。使用try对错误进行捕捉,使用do-catch对错误进行处理。
        do {
            try throwError()
        } catch MyErrorType.ErrorReason1 {
            print("错误原因: 1")
        }catch MyErrorType.ErrorReason2 {
            print("错误原因: 2")
        }catch {
            print("错误原因: 3")
        }

2.使用结构体为错误处理添加Reason

  • 使用结构体来遵循ErrorType协议, 可以在抛出错误时,给自定义错误类型提供错误原因。
  • 2.1使用结构体创建错误类型,下方名为MyErrorType的结构体遵循了ErrorType协议,并且在MyErrorType结构体中,声明了一个reason常量,该reason常量中存储的就是错误原因
struct MyErrorType2: ErrorType {
    let reason1: String
    let reason2: String
}
  • 2.2上面定义完错误类型结构体后,在错误抛出中就可以使用了。在错误抛出时,可以传入一个错误原因
func throwError2() throws {
        let test: Int? = nil
        
        guard test != nil else {
            throw MyErrorType2(reason1: "原因1", reason2: "原因2")
        }
    }
  • 2.3最后要对抛出的错误进行do-catch处理,在处理时,可以对错误原因进行打印,错误原因存储在error中
        do {
            try throwError2()
        } catch {
            print(error)
        }

3.使String类型遵循ErrorType协议,直接使用String提供错误原因

  • 这种方式最为简单
extension String: ErrorType {
    
}

func throwError3() throws {
    let test: Int? = nil
    
    guard test != nil else {
        throw "error"
    }
}

do {
    try throwError3()
} catch {
    print(error)
}

相关文章

  • Swift 基础(0) - 协议、枚举 、异常

    面向协议 面向对象的问题: 不能实现多继承,且会导致继承关系变得复杂 面向协议的事例: 实现统一加载 nib的 协...

  • Swift枚举高级用法(Enum)

    关于swift的枚举 一 swift对于枚举的扩展性(Enum) 枚举的继承(继承任何类和协议,目前除了swift...

  • Swift 枚举(enum)详解

    Swift基础语法总结,来自苹果官方文档: 枚举(Enumeration) 枚举在Swift中是 first-cl...

  • Swift5 基础教程与进阶合集

    Swift5 基础 Swift5 基础(一)Swift编译流程、基础语法、流程控制、函数、枚举[https://w...

  • Swift学习笔记-协议

    Swift中的协议类似于Java中的接口,不过在Swift中,结构体,枚举,类都能使用协议 基本用法 符合多个协议...

  • Swift 枚举

    Swift的枚举在功能上比OC强了很多,在Swift中枚举更倾向于类了 常规用法 成员变量,方法及协议 enum有...

  • iOS | Swift5.0学习 & 总结(三)

    Swift 协议 1.协议介绍 协议可以用来定义方法、属性、下标的声明,协议可以被枚举、结构体、类遵守(多个协议之...

  • iOS开发 - 「Swift 学习」Swift语言标识符命名规则

    Swift中变量、常量、方法、函数、枚举、结构体、类、协议等命名规则: 开发中需要对 变量、常量、方法、函数、枚举...

  • 基本语法

    swift基本语法 五种类型 枚举(enum),结构体(struct),类(class),协议(protocol)...

  • Extensions

    swift中扩展适用于类、结构体、枚举和协议 swift中的extension类似于Oc中的categories,...

网友评论

      本文标题:Swift 基础(0) - 协议、枚举 、异常

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