swift 在UI线程中执行代码的闭包样式的替代方法

rlcwz9us  于 5个月前  发布在  Swift
关注(0)|答案(2)|浏览(50)

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

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

字符串
在闭包内部访问uiThreadFuncparms是可能的,因为闭包从它们的“周围上下文”捕获变量。
但是,假设我不喜欢Swift风格的编程(在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没有参数。因此,我不能将uiThreadFuncparms传递给这个块。
我可以将uiThreadFuncparms存储为静态变量,但需要使其对多线程友好。
有没有一种更简单的方法可以在UIThread中使用DispatchQueue.main而不使用闭包?

gwo2fgha

gwo2fgha1#

在我正在做的项目中,函数中间不包含匿名代码块是一种惯例,它没有描述自然的执行流程
所以,你可以让这个“不”匿名:

// 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))


可以说更容易理解。你

wd2eg0qa

wd2eg0qa2#

这对你有帮助吗?
test来触发它,updateViewuiThreadFunc的一个示例

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 vs performSelector

相关问题