2016-08-04 4 views
1

Я создал класс, чем упростил реализацию разработчика. В методах Datasource UIPickerView я возвращаю значения из закрытия. Пример:Запуск закрытия по основной теме

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

Я использую то же самое для всех методов источника данных. Когда я запускаю приложение, он отображает сборщик на экране без каких-либо данных. Проблема в том, что я получаю данные от закрытий, которые, в свою очередь, не работают в основном потоке.

Есть ли способ запустить это закрытие основного потока и убедиться, что он возвращает значение, подходящее для типа возвращаемого значения функции источника данных? (Например, из приведенного выше примера, то замыкание возвращает Int)

EDIT:

Я знаю, используя 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 (Просмотр ли Load):

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

Пожалуйста, обратите внимание, что я удалил, выделяют вспомогательных функций между таким образом, чтобы вы фокусируетесь на основной части кода.

Разработчик может передать логику, которую он хочет, в переменных замыканий.

+0

Вы можете использовать 'dispatch_async (dispatch_get_main_queue()) {// Do your stuff}', чтобы получить основной поток внутри закрытия. Вы можете решить поместить в него весь код закрытия или просто когда вы закончили некоторые вещи раньше. – Larme

+0

Обратите внимание, что команда return self.pickerNumberOfRows! (Component: 0) не будет автоматически возвращать это значение в closOnMainThread, но только для закрытия dispatch_async (и никто не читает это возвращаемое значение в вашем примере). Мое предложение: используйте Семафоры (https://www.raywenderlich.com/79150/grand-central-dispatch-tutorial-swift-part-2). –

+0

вы не можете поместить 'dispatch_async' в' shutOnMainThread', как это. Это асинхронный процесс, поэтому он будет возвращать 0, определенный за пределами блока GCD. Поэтому внутри кода закрытия должна быть какая-то проблема. Отправьте это тоже. – RJE

ответ

1

Надеюсь, что я не нашел в настоящее время. В этом блоке вы можете запустить любой код и выполнить его на главной теме.

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

Вы можете запустить это знать, если вы находитесь на главном потоке или нет:

NSThread.isMainThread() 

EDIT

То, что вы ищете есть InstEd возвращения синхронизации ответа: - > 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 
     } 
+0

Спасибо за ответы. В случае, если я собираюсь использовать ваш метод, как вы собираетесь обращаться с вызовом someLongProcessTaskAndReturnCompenents в методе данных источника данных выбора? – user5440039

+0

Весь код, который вы вставили, работает в основном потоке. Если вам нужен конкретный ответ для вашего случая, в вашем вопросе показать, что именно вы имеете дело с такой задачей. Являются ли данные, отображаемые вами на экране сервером? – MCMatan

+0

Я все еще тестирую код, поэтому данные статичны. Разве закрытие не выполняется в другом потоке при запуске? Иногда, когда я запускаю приложение и задерживаю обед через точку останова, данные появляются, а затем начинают исчезать при прокрутке через них. Я думаю, основная проблема в том, как я читаю данные из закрытий. Вот почему я поднял вопрос о запуске их в основной теме. – user5440039

0

Вы не можете поставить dispatch_async в closureOnMainThread подобное. Это асинхронный процесс, поэтому он будет возвращать 0, определенный за пределами блока GCD. Поэтому внутри кода закрытия должна быть какая-то проблема.

Его должно быть синхронно не асинхронным.

Так что попробуйте немного вот так. - Это всего лишь пример кода. Предполагая 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 
} 
-1

Ладно, проблема даже не связана с прорастающих/закрытия. Проблема заключалась в использовании пусть или вара в контроллере представления, где я инстанцирование пользовательских палитр. Вот новая реализация контроллера:

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

Спасибо за каждого, кто поделился своими ответами.

+0

Это не имеет абсолютно никакого отношения к вашему оригинальному вопросу. – MCMatan

+0

@MCMatan хорошо, это было мое решение проблемы. – user5440039

Смежные вопросы