繁体   English   中英

在主线程上运行闭包

[英]Run closure on main thread

我创建了一个类,使开发人员更容易实现选择器视图。 在 UIPickerView 数据源方法中,我从闭包中返回值。 示例:

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return pickerNumberOfRows!(component: component)
}

我对所有数据源方法使用相同的东西。 当我运行该应用程序时,它会在屏幕上显示没有数据的选择器。 问题是我从闭包接收数据,而这些数据又没有在主线程上运行。

有没有办法在主线程上运行该闭包并确保它返回适合数据源函数返回值类型的值? (例如,从上面的例子中,闭包将返回一个 Int)

编辑:

我知道使用 dispatch_async。 但是,就我而言,它对我没有帮助。 假设我创建了一个在主线程上运行闭包的函数,并需要返回它看起来像这样的值:

func closureOnMainThread()->Int{
    dispatch_async(dispatch_get_main_queue()) {
        // Run your code here
        return self.pickerNumberOfRows!(component: 0)
    }
    return 0
}

但是,上面的函数存在一个问题,即在返回调度块内的值之前返回 0。

编辑2:使事情清楚。 我的代码包含一个用于选择器的自定义类和一个实现它的 UIViewController:

class CustomPickerView: NSObject, UIPickerViewDelegate, UIPickerViewDataSource {

        var pickerNumberOfRows: ((component: Int)->Int)?

        //MARK: UIPickerViewDatasource Methods
        func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
            return pickerNumberOfRows!(component: component)
        }

        func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
            return pickerNumberOfComponents!()
        }

        func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {print("Hello")
            return pickerRowTitle!(forRow: row, inComponent: component)
        }

        //MARK: UIPickerViewDelegate Methods
        func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
            pickerDidSelect!(row: row, component: component)
        }
    }

UIViewController(视图已加载):

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let picker = CustomPickerView(parent: self)

        picker.pickerNumberOfRows = { component in
            return 10
        }
    }

请注意,我删除了中间的辅助功能,以便您专注于主要代码部分。

开发者可以在闭包的变量中传入他想要的逻辑。

希望我目前理解。 在这个块中你可以运行任何代码,它会在主线程上执行。

dispatch_async(dispatch_get_main_queue()) { 
            // Run your code here
        }

您可以运行它以了解您是否在主线程上:

NSThread.isMainThread()

编辑

您正在寻找的是,无需返回同步响应:-> Int

您应该返回一个块,异步响应:

func someLongProcessTaskAndReturnCompenents(completion: (components: Int)->Void){

    //Here you can do your long process task on back thread...
                    dispatch_async(dispatch_get_main_queue()) {

                        completion(self.pickerNumberOfRows!(component: 0))
                    }
         }

现在当你运行它时,响应将返回同步:

someLongProcessTaskAndReturnCompenents { (components) in
            //Your logic after response
        }

你不能像这样将dispatch_async放在closureOnMainThread中。 这是一个异步过程,因此它将返回在 GCD 块之外定义的 0。 所以关闭代码中一定存在一些问题。

它必须是同步而不是异步的。

所以尝试一些这样的。 - 这只是一个示例代码块。 假设pickerNumberOfRows将在同一线程上返回一个 Int。(我使用dispatch_sync而不是dispatch_async

func closureOnMainThread()->Int{
    var x = 0;
    if (NSThread.isMainThread() == true) {
        x = self.pickerNumberOfRows!(component: 0) 
    } else {
        dispatch_sync(dispatch_get_main_queue()) {
            x = self.pickerNumberOfRows!(component: 0)
        }
    }
    return x
}

好的,问题甚至与线程/闭包无关。 问题在于在我实例化自定义选择器的视图控制器中使用letvar 这是一个新的视图控制器实现:

var picker: HBPickerView?

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    picker = HBPickerView(parent: self)

    picker!.presentPicker()
}

感谢所有分享答案的人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM