iOS9 Tutorials学习笔记(一)

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
  }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容