美文网首页
iOS9 Tutorials学习笔记(一)

iOS9 Tutorials学习笔记(一)

作者: 懒得起名的伊凡 | 来源:发表于2016-01-12 22:28 被阅读68次

    1、repeat的用法

    var i = 0
    repeat{
    print("i = \(i)")
    i++
    }while(i < 10)
    

    和之前的 do while 是一样的

    2、guard的用法

    guard 的可以理解为对某项条件的判定,如果为false,则执行else代码块内容,否则就直接往下执行

    //比较数字是否比10大
    func greaterThan10(num:NSInteger){
        guard num > 10 else{
            print("小于10")
            return
        }
        print("符合条件")
    }
    
    greaterThan10(20)
    

    3、Error Handling 的用法

    在Swift2.0之后,方法可以使用throws来抛出异常。来处理方法执行中可能发生的异常。简单介绍一下异常的处理实现流程。
    定义一个会抛出异常的方法,这里定义了一个protocol

    //:定义一个protocol
    protocol JSONParsable{
        static func parse(json:[String:AnyObject]) throws -> Self
    }
    

    定义抛出异常的类型

    //:定义错误类型
    enum ParseError:ErrorType{
       case MissingAttribute(message:String)
    }
    

    定义一个结构体来实现异常,抛出各种错误类型

    //: 定义一个 struct来实现JSONParsable,并抛出错误
    struct Person:JSONParsable {
        let firstName:String
        let lastName:String
    
        static func parse(json: [String : AnyObject]) throws -> Person {
            //哎,这里用到了guard ,注意
            guard let firstName = json["first_name"] as? String     else{
                let message = "Expected first_name String"
                throw ParseError.MissingAttribute(message: message)
            }
        
            guard let lastName = json["last_name"] as? String else{
                let message = "Expected last_name String"
            throw ParseError.MissingAttribute(message: message)
            }
            return Person(firstName: firstName, lastName: lastName)
        }    
    }
    

    异常状况的处理

    //: 处理错误异常
    do{
        let person = try Person.parse(["first_name":"first"])
    }catch ParseError.MissingAttribute(let message){
        print(message)
    }catch{
        print("Unexpected Error Type")
    }
    

    当然了,如果确定使用该方法是不会产生异常的,可以用!来直接获取,如果采取这种方式,所传数据格式不正确,则会直接编译错误。

    //: 如果确定不会抛出异常,可以直接使用 try!
    let person1 = try! Person.parse(["first_name":"first","last_name":"last"])
    

    或者使用?来获取

    //: 或者使用 try? 来确定是否可用
    if let person2 = try? Person.parse(["first_name":"fir"]){
        print("可以解析出实例")
    }
    else{
        print("出问题了")
    }
    

    4、String Validator 主要学习返回多个错误的方法

    总结一下上述知识点的使用方法,实现一个字符串的判定

    先添加一个String类型的扩展

    public extension String{
        public func startsWithCharacterFromSet(set:NSCharacterSet) -> Bool{
            guard !isEmpty else{
                return false
            }
            return rangeOfCharacterFromSet(set, options: [], range: startIndex ..< startIndex.successor()) != nil
        }
    
        public func endsWithCharacterFromSet(set:NSCharacterSet) -> Bool{
            guard !isEmpty else{
                return false
            }
            return rangeOfCharacterFromSet(set, options: [], range: endIndex.predecessor() ..< endIndex) != nil
        }  
    }
    

    定义一下错误类型

    enum StringValidationError: ErrorType, CustomStringConvertible {
    
      case MustStartWith(set: NSCharacterSet, description: String)
      case MustContain(set: NSCharacterSet, description: String)
      case MustEndWith(set: NSCharacterSet, description: String)
    
      case CannotContain(set: NSCharacterSet, description: String)
      case CanOnlyContain(set: NSCharacterSet, description: String)
      case ContainAtLeast(set: NSCharacterSet, count: Int, description: String)
    
      case MinLengthNotReached(Int)
      case MaxLengthExceeded(Int)
    
      var description: String {
        let errorString: String
        switch self {
        case .MustStartWith(_, let description):
          errorString = "Must start with \(description)."
        case .MustEndWith(_, let description):
          errorString = "Must end with \(description)."
        case .MustContain(_, let description):
          errorString = "Must contain \(description)."
        case .CannotContain(_, let description):
          errorString = "Cannot contain \(description)."
        case .CanOnlyContain(set: _, let description):
          errorString = "Can only contain \(description)."
        case .ContainAtLeast(_, let count, let description):
          errorString = "Must contain at least \(count) \(description)."
        case .MinLengthNotReached(let minChars):
          errorString = "Must be at least \(minChars) characters."
        case .MaxLengthExceeded(let maxChars):
          errorString = "Must be shorter than \(maxChars) characters."
        }
        return errorString
      }
    }
    

    这里注意协议CustomStringConvertible的使用方式,实现description方法。
    简单实现一下每次只返回一个错误的情况(上面有,不多说)

    protocol StringValidationRule{
        func validate(string:String) throws -> Bool
        var errorType:StringValidationError{get}
    }
    
    //判定是否是字母开头的
    struct StartsWithCharacterStringValidationRule:StringValidationRule {
    
        let characterSet:NSCharacterSet
        let description:String
        var errorType:StringValidationError{
            return .MustStartWith(set: characterSet, description: description)
        }
    
        func validate(string: String) throws -> Bool {
            if string.startsWithCharacterFromSet(characterSet){
                return true
            }else{
                throw errorType
            }
        }
    }
    
    let letterSet = NSCharacterSet.letterCharacterSet();
    
    let startsWithRule = StartsWithCharacterStringValidationRule(characterSet: letterSet, description: "letter")
    do {
        try startsWithRule.validate("foo")
        try startsWithRule.validate("12")
    }catch let error{
        print(error)
    }
    

    接下来实现返回多个判定结果
    实现协议

    protocol StringValidator{
        var validationRules:[StringValidationRule] {get}
        func validate(string:String) -> (valid:Bool,errors:[StringValidationError])
    }
    

    使用extension来实现协议方法的一个默认实现

    extension StringValidator{
        func validate(string:String) -> (valid:Bool,errors:[StringValidationError]){
            var errors = [StringValidationError]()
            for rule in validationRules{
                do{
                    try rule.validate(string)
                }catch let error as StringValidationError{
                    errors.append(error)
                }catch let error{
                    fatalError("Unexpected error type:\(error)")
                }
            }
            return (valid:errors.isEmpty,errors:errors)
        }
    }
    

    使用结构体来实现该协议

    struct StartsAndEndsWithStringValidator: StringValidator {
        let startsWithSet:NSCharacterSet
        let startsWithDescription:String
        let endsWithSet:NSCharacterSet
        let endsWithDescription:String
    
        var validationRules:[StringValidationRule]{
            return [
                StartsWithCharacterStringValidationRule(characterSet: startsWithSet, description: startsWithDescription),
                EndsWithCharacterStringValidationRule(characterSet: endsWithSet, description: endsWithDescription)
            ]
        }
    
        //这里没有实现方法validate也不会报错,是因为之前已经实现过默认,值得学习该方法
    }
    

    接下来就是实现了

    let numberSet = NSCharacterSet.decimalDigitCharacterSet()
    let startsAndEndWithValidator = StartsAndEndsWithStringValidator(startsWithSet: letterSet, startsWithDescription: "letter", endsWithSet: numberSet, endsWithDescription: "number")
    startsAndEndWithValidator.validate("foo").errors.description
    

    5、defer的使用

    使用defer { ... }语法来确保在当前作用域内的代码无论在哪儿结束,在结束之前都会执行defer代码块里的代码

    func testDefer(){
        print("执行defer之前的代码")
    
        defer{
            print("结束之前执行defer")
        }
    
        print("执行defer之后的代码")
    }
    
    testDefer()
    

    打印顺序为:
    执行defer之前的代码
    执行defer之后的代码
    结束之前执行defer

    6、Pattern Matching (模式匹配)

    在开始之前先记录一下map的一种用法,用来取出数组中同一类型的数据

    struct Student {
        var name:String
        var id:String
    }
    
    var students:[Student] = []
    //添加数据
    for i in 0...10{
        let student = Student(name: "name\(i)", id: "id\(i)")
        students.append(student)
    }
    
    let names = students.map{$0.name}
    //打印查看结果
    for name in names{
        print(name)
    }
    

    第一种
    for...in中使用where语句

    let names = ["Charlie","Chris","Mic","John","Craig","Felipe"]
    var namesThatStartWithC = [String]()
    for cName in names where cName.hasPrefix("C") {
        namesThatStartWithC.append(cName)
    }
    

    结果:
    ["Charlie", "Chris", "Craig"]

    第二种

    //针对特定的case 输出
    for case "name2" in names{
        print("name2")
    }
    

    第三种
    if case 可以直接用来判断某个枚举对象属于哪一分支

     var slapLog = ""
     for author in authors {
       if case .Late(let daysLate) = author.status where daysLate > 2 {
         slapLog += "Ray slaps \(author.name) around a bit with a large trout \n"
       }
     }
    

    6、OptionSetType

    创建自己的OptionSet,就是声明一个实现了OptionSetType协议的结构体

    struct RectangleBorderOptions: OptionSetType {
      let rawValue: Int
    
      init(rawValue: Int) { self.rawValue = rawValue }
    
      static let Top = RectangleBorderOptions(rawValue: 0)
      static let Right = RectangleBorderOptions(rawValue: 1)
      static let Bottom = RectangleBorderOptions(rawValue: 2)
      static let Left = RectangleBorderOptions(rawValue: 3)
      static let All: RectangleBorderOptions = [Top, Right, Bottom, Left]
    }
    

    7、判定系统

    有些新的 APIs 不能在旧版本的系统上使用,所以使用时需要判定当前的系统版本

    guard #available(iOS 9.0,*)else{
      print("The OS version below 9.0")
      return
    }
    

    比如我们使用 NSUserActivity这个类(最低支持8.0),并且app最低版本支持设置为7.0,此时将会出现错误

    public var userActivity: NSUserActivity {
    let activity = NSUserActivity(activityType: Employee.domainIdentifier)
    activity.title = name
    activity.userInfo = userActivityUserInfo
    activity.keywords = [email, department]
    activity.contentAttributeSet = attributeSet
    return activity
    

    }
    解决方案一:

      public var userActivity: NSUserActivity {
        let activity = NSUserActivity(activityType:     Employee.domainIdentifier)
        activity.title = name
        activity.userInfo = userActivityUserInfo
        if #available(iOS 9.0, *) {
            activity.keywords = [email, department]
        } else {
            // Fallback on earlier versions
        }
        if #available(iOS 9.0, *) {
            activity.contentAttributeSet = attributeSet
        } else {
            // Fallback on earlier versions
        }
        return activity
      }
    

    解决方案二:

    @available(iOS 9.0, *)
      public var userActivity: NSUserActivity {
        let activity = NSUserActivity(activityType: Employee.domainIdentifier)
        activity.title = name
        activity.userInfo = userActivityUserInfo
        activity.keywords = [email, department]
        activity.contentAttributeSet = attributeSet
        return activity
      }

    相关文章

      网友评论

          本文标题:iOS9 Tutorials学习笔记(一)

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