Swift Tips笔记
2016-01-04 15:59
399 查看
“??”操作符可以判断输入并在当左侧的值是非 nil 的 Optional 值时返回其 value,当左侧是 nil 时返回右侧的值.
例:
Swift 中 Selector 只能使用字符串在生成,这样难以重构,并且无法在编译期间进行检查,可以利用柯里化进行封装改造。
代码如下:
写一个可变参数的函数只需要在声明参数时在类型后面加上 “…”, 在同一个方法中只能有一个参数是可变的,可变参数都必须是同一种类型.
例:
如果有一个类型 Class 同时实现了 A 和 B接口(Protocol),为了避免冲突,在调用前应该进行类型转换。
例:
Swift中常用的原生容器类型有Array、Dictionary、Set,它们都是泛型的,也就是说在一个集合中只能放同一个类型的元素。(OC可以用NSArray放不同类型的元素)
Swift可以考虑使用enum封装(利用enum可以带有值的特性)
代码如下:
Lazy修饰符和map、filter这类接受闭包的方法写在一起,让整个行为变成延时进行,在不需要完全运行,可能提前退出的情况下,可以优化性能。
代码如下:
Swift内建类型Array和Dictionary都是值类型,也就是在传递和赋值时会进行复制,而Cocoa中的NSMutableArray和NSMutableDictionary是引用类型。因此,在需要处理大量数据并频繁操作(增减)其中元素时,选择NSMutableArray和NSMutableDictionary更好,而对于容器内条目小而容器本身数目多的情况,选择Array和Dictionary更好。
GCD实现延时调用(delay)和取消执行(cancel)
实现代码:
调用:
Swift中如果想对属性进行KVO观察,需要添加dynamic关键字,如果无法修改源码,需要重载相关类。比起改写,更推荐使用swift第三方框架Observable-Swift
Swift实现Associated Object为已有类型添加属性
测试:
摘录来自: 王巍 (onevcat). “Swifter - 100 个 Swift 必备 Tips (第二版)”。 iBooks.
例:
var level: Int? var startLevel = 1 var currentLevel = level ?? startLevel //currentLevel等于默认值1
Swift 中 Selector 只能使用字符串在生成,这样难以重构,并且无法在编译期间进行检查,可以利用柯里化进行封装改造。
代码如下:
protocol TargetAction { func performAction() } struct TargetActionWrapper<T:AnyObject>: TargetAction { weak var target: T? let action: (T) -> () -> () func performAction() { if let t = target { action(t)() } } } enum ControlEvent { case TouchUpInside case ValueChanged } class Control { var actions = [ControlEvent: TargetAction]() func setTarget<T:AnyObject>(target: T, action: (T) -> () -> (), controlEvent: ControlEvent) { actions[controlEvent] = TargetActionWrapper(target: target, action: action) } func removeTargetForControlEvent(controlEvent: ControlEvent) { actions[controlEvent] = nil } func performActionForControlEvent(controlEvent: ControlEvent) { actions[controlEvent]?.performAction() } }
写一个可变参数的函数只需要在声明参数时在类型后面加上 “…”, 在同一个方法中只能有一个参数是可变的,可变参数都必须是同一种类型.
例:
“func sum(input: Int...) -> Int { return input.reduce(0, combine: +) } print(sum(1,2,3,4,5)) // 输出:15”
如果有一个类型 Class 同时实现了 A 和 B接口(Protocol),为了避免冲突,在调用前应该进行类型转换。
例:
protocol A { func bar() -> Int } protocol B { func bar() -> String } class Class: A, B { func bar() -> Int { return 1 } func bar() -> String { return "Hi" } } let instance = Class() let num = (instance as A).bar() // 1 let str = (instance as B).bar() // "Hi"
Swift中常用的原生容器类型有Array、Dictionary、Set,它们都是泛型的,也就是说在一个集合中只能放同一个类型的元素。(OC可以用NSArray放不同类型的元素)
Swift可以考虑使用enum封装(利用enum可以带有值的特性)
代码如下:
enum IntOrString { case IntValue(Int) case StringValue(String) } let mix = [IntOrString.IntValue(1), IntOrString.StringValue("two"), IntOrString.IntValue(3)] mix.map { (obj) -> () in switch obj { case let .IntValue(i): print(i) case let .StringValue(str): print(str) } }
Lazy修饰符和map、filter这类接受闭包的方法写在一起,让整个行为变成延时进行,在不需要完全运行,可能提前退出的情况下,可以优化性能。
代码如下:
let data = 1...3 let result = data.lazy.map { (i: Int) -> Int in print("正在处理 \(i)") return i * 2 } print("准备访问结果") for i in result { print("操作后结果为 \(i)") } print("操作完毕") /////// 输出结果 // 准备访问结果 // 正在处理 1 // 操作后结果为 2 // 正在处理 2 // 操作后结果为 4 // 正在处理 3 // 操作后结果为 6 // 操作完毕
Swift内建类型Array和Dictionary都是值类型,也就是在传递和赋值时会进行复制,而Cocoa中的NSMutableArray和NSMutableDictionary是引用类型。因此,在需要处理大量数据并频繁操作(增减)其中元素时,选择NSMutableArray和NSMutableDictionary更好,而对于容器内条目小而容器本身数目多的情况,选择Array和Dictionary更好。
GCD实现延时调用(delay)和取消执行(cancel)
实现代码:
typealias Task = (cancel: Bool) -> Void func delay(time: NSTimeInterval, task:()->()) -> Task? { func dispatch_later(block:()->()) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(time*Double(NSEC_PER_SEC))), dispatch_get_main_queue(), block) } var closure: dispatch_block_t? = task var result: Task? let delayedClosure: Task = { cancel in if let internalClosure = closure { if (cancel == false) { dispatch_async(dispatch_get_main_queue(), internalClosure) } } closure = nil result = nil } result = delayedClosure dispatch_later { () -> () in if let delayedClosure = result { delayedClosure(cancel: false) } } return result } func cancel(task:Task?) { task?(cancel: true) }
调用:
let task = delay(5.0, task: { print("Do sometiong 5 seconds later") }) //延迟5秒调用task cancel(task) //取消执行task
Swift中如果想对属性进行KVO观察,需要添加dynamic关键字,如果无法修改源码,需要重载相关类。比起改写,更推荐使用swift第三方框架Observable-Swift
“class MyClass: NSObject { var date = NSDate() } class MyChildClass: MyClass { dynamic override var date: NSDate { get { return super.date } set { super.date = newValue } } }”
Swift实现Associated Object为已有类型添加属性
“class MyClass: NSObject { var date = NSDate() } class MyChildClass: MyClass { dynamic override var date: NSDate { get { return super.date } set { super.date = newValue } } }”
测试:
func printTitle(input: MyClass) { if let title = input.title { print("Title:\(title)") } else { print("NO Title") } } let c = MyClass() printTitle(c) c.title = "I'm title" printTitle(c)
摘录来自: 王巍 (onevcat). “Swifter - 100 个 Swift 必备 Tips (第二版)”。 iBooks.
相关文章推荐
- 《swift2.0 官方教程中文版》 第2章-21扩展
- swift安装cocoapod遇到的一些坑
- Swift 之类的继承与类的访问权限
- Swift - Struct 與 Class 的差異性
- 《从零开始学Swift》学习笔记(Day 55)——使用try?和try!区别
- 《从零开始学Swift》学习笔记(Day 55)——使用try?和try!区别
- [ios][swift]使用swift闭包进行viewcontroller反向传值
- (十三) swift 真机调试,ios第三方类库打包
- Swift中的可选类型(Optional)
- Swift可选值OptionalOptional 问号 感叹号
- FM音乐播放器 基于豆瓣 api,swift,alamofire,sqlite.swift 等
- Swift2.1-自动引用计数
- Swift Functional Programming Tutorial
- 使用swift开发OSX应用
- Swift控制手电筒操作(iOS)
- swift中通知的使用
- Swift开发IOS-UITextField
- swift2.0中文文档
- Swift -- 方法
- iOS二维码扫描的实现(Swift)