首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Swift中设置目标与CADisplayLink实例间弱引用的CADisplayLink

如何在Swift中设置目标与CADisplayLink实例间弱引用的CADisplayLink
EN

Stack Overflow用户
提问于 2017-05-21 12:21:39
回答 3查看 2.3K关注 0票数 2

在Objective中,我们可以使用代理模式插入CADisplayLink以打破强引用:

代码语言:javascript
复制
WeakProxy *weakProxy = [WeakProxy weakProxyForObject:self];
self.displayLink = [CADisplayLink displayLinkWithTarget:weakProxy selector:@selector(displayDidRefresh:)];

然后,只需使displayLink在dealloc中失效。

代码语言:javascript
复制
- (void)dealloc
{
    [_displayLink invalidate];
}

然而,NSProxy似乎不能在Swift:https://bugs.swift.org/browse/SR-1715中被继承

我试着这样写:

代码语言:javascript
复制
weak var weakSelf = self    
displayLink = CADisplayLink(target: weakSelf!, selector: #selector(displayDidRefresh(dpLink:)))

它没有起作用。

我想知道在目标C中是否有实现这一目标的方法。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-05-21 15:06:40

更好的方法可能是使viewWill/DidDisappear中的显示链接失效,请参见

为了获取有用的信息。

如果这不是一个选项:让代理对象从NSObject而不是NSProxy继承。例如,给出了一个目标-C的解决方案。

这很容易被翻译成Swift 3:

代码语言:javascript
复制
class JAWeakProxy: NSObject {
    weak var target: NSObjectProtocol?

    init(target: NSObjectProtocol) {
        self.target = target
        super.init()
    }

    override func responds(to aSelector: Selector!) -> Bool {
        return (target?.responds(to: aSelector) ?? false) || super.responds(to: aSelector)
    }

    override func forwardingTarget(for aSelector: Selector!) -> Any? {
        return target
    }
}

然后它可以用作

代码语言:javascript
复制
displayLink = CADisplayLink(target: JAWeakProxy(target: self),
                            selector: #selector(didRefresh(dpLink:)))

你的方法

代码语言:javascript
复制
weak var weakSelf = self    
displayLink = CADisplayLink(target: weakSelf!, selector: #selector(displayDidRefresh(dpLink:)))

不工作,因为它在初始化weakSelf并将强引用传递给作为目标的self时对CADisplayLink进行解压缩。

票数 4
EN

Stack Overflow用户

发布于 2018-02-15 15:52:59

这个代理类应该可以正常工作。别忘了在脱欧之前失效。

代码语言:javascript
复制
import UIKit

class CADisplayLinkProxy {

    var displaylink: CADisplayLink?
    var handle: (() -> Void)?

    init(handle: (() -> Void)?) {
        self.handle = handle
        displaylink = CADisplayLink(target: self, selector: #selector(updateHandle))
        displaylink?.add(to: RunLoop.current, forMode: .common)
    }

    @objc func updateHandle() {
        handle?()
    }

    func invalidate() {
        displaylink?.remove(from: RunLoop.current, forMode: .common)
        displaylink?.invalidate()
        displaylink = nil
    }
}

用法:

代码语言:javascript
复制
class ViewController: UIViewController {

    var displaylinkProxy: CADisplayLinkProxy?

    override func viewDidLoad() {
        super.viewDidLoad()
        displaylinkProxy = CADisplayLinkProxy(handle: { [weak self] in
            self?.updateAnything()
        })
    }

    @objc func updateAnything() {
        print(Date())
    }
}
票数 3
EN

Stack Overflow用户

发布于 2020-06-05 16:00:11

另一种解决方案是,该解决方案将代理/ objc运行时隐藏在其外部API中。只要DisplayLink被变量引用,它就能存活多久。一旦变量超出作用域或设置为零,CADisplayLink将失效,以便也可以对目标进行删除。

代码语言:javascript
复制
import Foundation
import UIKit

/// DisplayLink provides a block based interface for CADisplayLink.
/// The CADisplayLink is invalidated upon DisplayLink deinit.
///
/// Usage:
/// ```
/// let displayLink = DisplayLink { caDisplayLink in print("Next frame scheduled \(caDisplayLink.targetTimestamp)") }
/// ```
///
/// Note: Keep a reference to the DisplayLink.
final class DisplayLink {
    let displayLink: CADisplayLink

    init(runloop: RunLoop? = .main, prepareNextFrame: @escaping (CADisplayLink) -> ()) {
        displayLink = CADisplayLink(
            target: DisplayLinkTarget(prepareNextFrame),
            selector: #selector(DisplayLinkTarget.prepareNextFrame))

        if let runloop = runloop {
            displayLink.add(to: runloop, forMode: .default)
        }
    }

    deinit {
        displayLink.invalidate()
    }
}

private class DisplayLinkTarget {
    let callback: (CADisplayLink) -> ()

    init(_ callback: @escaping (CADisplayLink) -> ()) {
        self.callback = callback
    }

    @objc func prepareNextFrame(displaylink: CADisplayLink) {
        callback(displaylink)
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44096793

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档