• Swift Tips笔记


    “??”操作符可以判断输入并在当左侧的值是非 nil 的 Optional 值时返回其 value,当左侧是 nil 时返回右侧的值.

    例:

    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. 

  • 相关阅读:
    hdu5091(线段树+扫描线)
    hdu2874(tarjan)
    hdu4252
    poj2452(RMQ+二分)
    Dragon Balls HDU
    CF803
    poj1962(带权并查集)
    hdu2818(带权并查集)
    GitHub入门之一:使用github下载项目 .
    (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间
  • 原文地址:https://www.cnblogs.com/liuliuliu/p/5099190.html
Copyright © 2020-2023  润新知