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
}