替代闭包风格在 UI 线程中执行代码

问题描述 投票:0回答:2

从后台线程,当UI需要更新时,需要使用async(execute:)函数发布到DispatchQueue.main,如下所示:

static func executeInUIThread(_ uiThreadFunc: @escaping (Any?) -> Void, _ parms: Any?) {
  DispatchQueue.main.async {
    // Update UI 
    uiThreadFunc(parms)
  }
}

可以在闭包内访问

uiThreadFunc
parms
,因为闭包从其“周围上下文”捕获变量

但是可以说,我不喜欢 lambda 风格(在 swift 中称为闭包)编程。我怎样才能在不关闭的情况下做到这一点?

我尝试了以下方法:

static func executeInUIThread(_ uiThreadFunc: @escaping (Any?) -> Void, _ parms: Any?) {
  let workItem = DispatchWorkItem(block: EventLoopMgr.InternalExecuteInUIThread)

  DispatchQueue.main.async(execute: workItem)
}

private static func InternalExecuteInUIThread() {
  // How to execute the uiThreadfunc? This block doesn't take any parameters.
}

它不起作用,因为初始化 DispatchWorkItem 时的block不带任何参数。因此,我无法将

uiThreadFunc
parms
传递到此块。

我可以将

uiThreadFunc
parms
存储为静态变量,但随后需要使其支持多线程。

是否有一种更简单的方法可以使用 DispatchQueue.main 在 UIThread 中执行但不使用闭包?

ios swift ui-thread
2个回答
2
投票

这对你有帮助吗?

test
来触发它,
updateView
uiThreadFunc

的一个示例
func test() {
    let aFunc = #selector(updateView)
    let success = executeInUIThread(caller: self, uiThreadFunc: aFunc, "xxx")
}

func executeInUIThread(caller: NSObject, uiThreadFunc: Selector, _ parms: Any?) -> Bool {
    if caller.responds(to: uiThreadFunc) {
        caller.performSelector(onMainThread: uiThreadFunc, with: parms, waitUntilDone: false)
        return true
    } else {
        return false
    }
}

@objc func updateView(param: String) { }

欲了解更多信息,请 检查一下 GCD 与 PerformSelector


1
投票

在我正在从事的项目中,惯例是函数中间不要有匿名代码块。它没有描述执行的自然流程

好的,所以你可以让这个匿名:

// I made this generic for you :)
func executeInUIThread<T>(_ uiThreadFunc: @escaping (T) -> Void, _ parms: T) {
    func helper() {
        uiThreadFunc(parms)
    }
    DispatchQueue.main.async(execute: helper)
}

在这里,我为将在主队列上运行的代码块命名为

helper

从技术上讲,根据 Swift Guide,本地函数仍然算作闭包,但如果您想避免的只是“匿名”代码块,那么使用本地函数绝对可以实现这一点。

如果局部函数噪音太大,你可以将其移出

executeInUIThread
,如下所示:

func partiallyApply<T>(_ arg: T, to function: (T) -> Void) -> () -> Void {
    func helper() { function(arg) }
    return helper
}

然后你可以这样做:

DispatchQueue.main.async(execute: partiallyApply(parms, to: uiThreadFunc))

这可以说更具可读性。你

© www.soinside.com 2019 - 2024. All rights reserved.