在主线程

时间:2016-08-04 09:00:58

标签: ios swift multithreading closures

我创建了一个类,而不是让开发人员更容易实现选择器视图。在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
        }
    }

请注意我删除了其间的配件功能,以便您专注于主代码部分。

开发人员可以在闭包变量中传递他想要的逻辑。

3 个答案:

答案 0 :(得分:2)

希望我目前不准。在这个块中,您可以运行任何代码,它将在主线程上执行。

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

您可以运行此命令以了解您是否在主线程上:

NSThread.isMainThread()

修改

您正在寻找的是返回同步响应: - >诠释

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

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

现在,当您运行它时,响应将返回synchronized:

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

答案 1 :(得分:0)

您不能将 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
}

答案 2 :(得分:-1)

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

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()
}

感谢所有分享他们答案的人。