sagezhong

OC转Swift的开发体验
最近使用Swift把公司的一个OC项目重写了一遍,并且第一个版本已经通过了App Store的审核。在这里简单总结...
扫描右侧二维码阅读全文
30
2021/06

OC转Swift的开发体验

最近使用Swift把公司的一个OC项目重写了一遍,并且第一个版本已经通过了App Store的审核。在这里简单总结了一下OC转Swift的开发体验。

内存管理

区别

在使用OC开发iOS应用的使用,通常需要使用大量的内存管理语义,例如在使用ARC时Property中的strongweakassigncopy,而使用Swift时对此进行了大量的简化,因为Swift的基础数据类型的实现方式与OC不同。Swift的基础数据类型具有值语义,包括了常见的集合类型Array、Dictionary。所以在使用基础数据类型的时候,大多时候并不需要管理其内存。而对于引用类型,在Swift中还是和OC一样的,需要注意其内存管理,避免引用类型之间的循环应用,造成了内存泄露。

避免循环引用

所有使用自动引用计数的进行内存管理的语言都需要注意循环应用的问题。而在Swift中,类似之前OC中Property的内存语义,可以使用weak、和unowned,来避免引用类型之间的循环应用。两者之前的区别是使用weak标记的变量一定要是可选类型的,而使用unowned不能是可选类型。weak标记的变量如果被释放了会自动置为nil,而unowned则不会。所以说如果可以确定变量在使用其中不会被释放的话可以使用unowned,而不确定的话还是使用weak吧。当然,weak的性能还稍微更差一点。这一点就和OC的weak和unsafe_unretained一样。

而在实际的开发中,最经常遇见的会造成循环引用的场景则是:

  1. 使用代理设计模式
  2. 对象持用的闭包内部又持有了对象本身

使用代理设计模式避免循环引用

protocol messageDelegate: AnyObject {
    func receiveMessage(msg: String)
}

class MessageSender {
    weak var delegate: messageDelegate?
    
    
    func requestMessageFromNetwork() {
        self.delegate?.receiveMessage(msg: "hello")
    }
}

class MessageReceiver: messageDelegate {
    
    var sender: MessageSender
    
    init() {
        sender = MessageSender()
        sender.delegate = self
    }
    
    func requestMessage() {
        sender.requestMessageFromNetwork()
    }
    
    func receiveMessage(msg: String) {
        print("receive message: \(msg)")
    }
}

总得来说,在引用类型可能会发生互相持有的时候,一定要保证一方被weak标记来避免循环引用。

对象持用的闭包内部又持有了对象本身

这也是一种常见的造成循环应用的情况,而且更加隐蔽。Swift中的Clouser(闭包)和OC中的Block一样,闭包中对任何其他元素的引用都是会被闭包自动持有的。如果我们闭包中使用了self,则会对对象本身进行持有,而如果对象本身直接或者间接持有了闭包则造成了循环应用。

class UserPageViewController: UIViewController {
    
    lazy var viewModel = UserPageViewModel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        initListner()
        
        initData()
        
    }
    
    func initListner() {
        self.viewModel.userDataDidUpdate = {
            [weak self] in
            guard let strongSelf = self else {return}
            print("get username: \(strongSelf.viewModel.userName)")
        }
    }
    
    func initData() {
        viewModel.requestUserData()
    }
}

typealias VoidCallback = () -> Void

class UserPageViewModel {
    var userName = ""
    var userDataDidUpdate: VoidCallback?
    
    func requestUserData() {
        userName = "hello"
        userDataDidUpdate?()
    }
}

在上面这个例子中UserPageVC-->UserPageViewModel-->userDataDidupdate-->UserPageVC,所以需要在闭包中对UserPageVC弱持有,和OC类似的,Swift中使用[weak self]即可对self弱持有。

总的来说,因为Swift还是使用自动引用计数来进行内存管理,和之前使用OC开发时候需要注意的是差不多的,不过Swift对内存管理进行了进一步的简化,使我们更容易上手。

Last modification:July 1st, 2021 at 08:04 pm
请随意赞赏

5 comments

  1. wzinjlwlob

    价值导向积极,彰显社会责任意识。

  2. felldktukd

    内容的丰富性和深度让人仿佛置身于知识的海洋,受益匪浅。

  3. qkbooquugh

    情感真挚自然,字里行间传递出强烈的感染力。

  4. nneesgtbnv

    想想你的文章写的特别好https://www.237fa.com/

  5. vhiqdeivvd

    想想你的文章写的特别好https://www.jiwenlaw.com/

Leave a Comment