从OC到Swift (二)

协议

只能被class继承的协议

protocol Runnable1: AnyObject{}
protocol Runnable2: class{}
@objc protocol Runnable3 {}
  • @objc修饰的协议,还可以暴露给OC去遵守实现
  • 可以通过@objc定义可选协议,这种协议只能被class遵守
@objc protocol Runnable{
    func run1()
    @objc optional func run2()
    func run3()
}

class Dog: Runnable {
    func run1() { print("Dog run1")}
    func run3() {print("Dog runn3")}
}
var d = Dog()
d.run1()
d.run3()

dynamic

  • @objc dynamic 修饰的内容会具有动态性,比如调用方法会走runtime那一套流程
class Dog: NSObject {
    @objc dynamic func test1() {}//走runtime机制
    func test2() {}//走虚表一套流程
}
var d = Dog()
d.test1()
d.test2()

KVC/KVO

  • Swift支持KVC/KVO的条件
    - 属性所在的类、监听器最终继承自NSObject(KVC/KVO也是依赖于runtime的)
    - 用@objc dynamic 修饰对应的属性

block方式的KVO

class Person: NSObject {
    @objc dynamic var age:Int = 0
    var observation:NSKeyValueObservation?
    override init() {
        super.init()
        observation = observe(\Person.age, options: .new, changeHandler: { person, change, in
            print(change.newValues as Any)
        })
    }
}

关联对象

  • 在Swift中,class依然可以使用关联对象
  • 默认情况,extension不可以增加存储属性,可以增加计算属性,因为计算属性本质是方法,不占用内存
protocol Runnable {
    
}
extension Runnable{
    
}
class Person:Runnable {
    var age = 0
}
extension Person{
    var weight = 0//报错:Extensions must not contain stored properties
}
  - 借助关联对象,可以实现类似`extension`为`class`增加存储属性的效果
extension Person{
    private static var AGE_KEY : Void?//这里用Void?或者bool类型,目的是为了省内存,Void?或者bool类型都只占用一个字节
    //类型存储属性,本质是全局变量
    var age:Int{
        get{
            objc_getAssociatedObject(self, &Person.AGE_KEY) as! Int
        }
        set {
            objc_setAssociatedObject(self, &Person.AGE_KEY, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
}
var p = Person()
p.age = 10
print(p.age)

资源名管理

  • 这种做法实际上是参考了Android的资源名管理方式
enum R{
    enum string:String {
        case add = "添加"
    }
    enum image:String {
        case logo
    }
    enum segue:String {
        case login_main
    }
}

let img = UIImage(named: R.image.logo.rawValue)
let btn = UIButton(type: .custom)
btn.setTitle(R.string.add.rawValue, for: .normal)
performSegue(withIdentifier: R.segue.login_main.rawValue, sender: self)

资源名管理的其他思路

enum R{
    enum image {
        static var logo = UIImage(named: "logo")
    }
    enum font {
        static func arial(_ size:CGFloat) -> UIFont?{
            UIFont(name: "Arial", size: size)
        }
    }
}

let img = R.image.logo
        let font = R.font.arial(14)

多线程开发 - 异步

//gcd
DispatchQueue.main.async {
      //拿到主线程
}
        
DispatchQueue.global().async {
     //拿到全局并发队列
     print(Thread.current)//打印当前线程
     DispatchQueue.main.async {
          //回到主线程
     }
}

或者:

let item = DispatchWorkItem{
    //子线程
    print("1",Thread.current)
}
DispatchQueue.global().async(execute: item)
item.notify(queue: DispatchQueue.main){
    //主线程
    
}

多线程开发 - 延迟

let time = DispatchTime.now()+3
        
DispatchQueue.main.asyncAfter(deadline: time){
     print("1")
}

多线程开发 - once

  • dispatch_once 在Swift中已被废弃,取而代之
    - 可以用类型属性或者全局变量/常量:静态的存储属性(static),也就是类型存储属性,他在程序运行过程中,只初始化一次,因为本质就是全局变量,全局变量在运动过程中只初始化一次,而且static修饰的属性默认是lazy的,所以只想走一次代码的可以用下面的方法
    - 默认自带 lazy + dispatch_once 效果
static var age:Int = getAge()
static func getAge() -> Int{
       print("getAge")
       return 0
}

print(Self.age)
print(Self.age)
print(Self.age)
//这种办法声明的getAge只会调用一次,即使是所在的ViewController被销毁之后重新创建,age也不会再走一遍初始化getAge的方法
fileprivate var initTask:Void = {
    print("init -------")
}()
let _ = initTask
let _ = initTask
//只走一次print("init -------")代码

多线程开发 - 加锁

import Foundation

public struct Cache{
    private static var data = [String:Any]()
    private static var lock = DispatchSemaphore(value: 1)//value值是几,就表示允许几条线程同时修改
    
    public static func get(_ key:String) -> Any?{
        data[key]
    }
    
    public static func set(_ key:String,_ value:Any){
        lock.wait()
        defer{lock.signal()}
        data[key] = value
    }  
}

或者:

import Foundation

public struct Cache{
    private static var data = [String:Any]()
    private static var lock = NSLock()
    
    public static func get(_ key:String) -> Any?{
        data[key]
    }
    
    public static func set(_ key:String,_ value:Any){
        lock.lock()
        defer {lock.unlock()}
        data[key] = value
    }
}

函数中有递归容易造成死锁,用递归锁解决

import Foundation

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

推荐阅读更多精彩内容