2015-01-23 2 views
1

У меня есть способ загрузить данные из веб-службы и заполнить массив, он отлично работает (назовем его «get_data»). Я использую этот массив («arr») как источник данных для представления picker («pv»), он также отлично работает, когда я запускаю свое приложение, pickerview заполнен элементами. Однажды я решил использовать «индикатор активности» («ai»), и теперь «pv» всегда пуст, и я понятия не имею, как его исправить. Следующий мой код:Как заполнить подборку данными и одновременно запустить индикатор активности?

- (void) viewDidLoad { 
[super viewDidLoad]; 
[ai startAnimation]; // ACTIVITY INDICATOR STARTS SPINNING. 
[self performSelector:@selector(get_data) // FILL ARRAY. 
      withObject:nil 
      afterDelay:0]; } 
//------------------------------------------------------------------- 
- (void) get_data { // CALL WEB SERVICE, FILL ARRAY WITH JSON DATA. 
[ai stopAnimation]; } // SPINNING STOPS AFTER LONG TASK. 
//------------------------------------------------------------------- 
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 
return 1; } 
//------------------------------------------------------------------- 
- (NSInteger)pickerView :(UIPickerView *)pickerView 
numberOfRowsInComponent:(NSInteger)component { 
return [arr count]; } 
//------------------------------------------------------------------- 
- (NSString *)pickerView:(UIPickerView *)pickerView 
      titleForRow:(NSInteger)row 
      forComponent:(NSInteger)component { 
return [arr objectAtIndex:row]; } 
//------------------------------------------------------------------- 
- (void) pickerView:(UIPickerView *)pickerView 
     didSelectRow:(NSInteger)row 
     inComponent:(NSInteger)component { 
index = [pv selectedRowInComponent:0]; } // INDEX IS A GLOBAL INT. 
//------------------------------------------------------------------- 
- (NSAttributedString *) pickerView:(UIPickerView *)pickerView 
       attributedTitleForRow:(NSInteger)row 
         forComponent:(NSInteger)component { 
NSString * title = [arr objectAtIndex:row]; 
NSAttributedString * attString = [[NSAttributedString alloc] 
           initWithString:title attributes: 
           @{NSForegroundColorAttributeName: 
           [UIColor blackColor]}]; 
return attString; } 

Я использовал «показатели деятельности», прежде чем с «performSelector», и они прекрасно работали. Я не понимаю, почему методы pickerview больше не работают с массивом, поэтому мой вопрос: как заполнить данные pickerview и одновременно запустить индикатор активности?

Если я изменить viewDidLoad, как это, pickerview работает, но индикатор активности не:

- (void) viewDidLoad { 
[super viewDidLoad]; 
/* [ai startAnimation]; // ACTIVITY INDICATOR STARTS SPINNING. 
[self performSelector:@selector(get_data) // FILL ARRAY. 
      withObject:nil 
      afterDelay:0]; */ 
[self get_data]; 
} 
+0

Попробуйте положить точку прерывания в любой из ваших источников данных источников данных, чтобы узнать, попадают ли они после завершения вашего веб-сервиса, а индикатор активности прекращается. И убедитесь, что 'arr' содержит объекты, которые, по вашему мнению, содержат. – Stonz2

+0

Дорогой Stonz2, я сделал то, что вы предложили, arr заполнен данными, но методы pickerview вообще не выполняются. –

ответ

2

При использовании performSelector:, выполняется в том же потоке, как если бы вы просто назвать селектор непосредственно.

- (void) viewDidLoad { 
    [super viewDidLoad]; 
    [ai startAnimation]; // ACTIVITY INDICATOR STARTS SPINNING. 
    [self performSelector:@selector(get_data) // FILL ARRAY. 
      withObject:nil 
      afterDelay:0]; 
} 

- (void) get_data { 
    // CALL WEB SERVICE, FILL ARRAY WITH JSON DATA. 
    [ai stopAnimation]; // SPINNING STOPS AFTER LONG TASK. 
} 

Это идентично:

- (void) viewDidLoad { 
    [super viewDidLoad]; 
    [ai startAnimation]; // ACTIVITY INDICATOR STARTS SPINNING. 
    [self get_data]; // FILL ARRAY. 
} 

или просто:

- (void) viewDidLoad { 
    [super viewDidLoad]; 
    [ai startAnimation]; // ACTIVITY INDICATOR STARTS SPINNING. 
    // CALL WEB SERVICE, FILL ARRAY WITH JSON DATA. 
    [ai stopAnimation]; // SPINNING STOPS AFTER LONG TASK. 
} 

Если веб-служба выполняется в другом потоке или блока и позволяет присоединять ответчик завершения, вы должны положить туда [ai stopAnimation];.

Если это не так, и вы синхронно вызываете веб-службу для данных по основному потоку (никогда не выполняют блокировки сетевых операций по основному потоку), вы могли бы сместить все это на фоновый поток:

- (void) viewDidLoad { 
    [super viewDidLoad]; 
    [ai startAnimation]; // ACTIVITY INDICATOR STARTS SPINNING. 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0L), ^{ 
    // CALL WEB SERVICE, FILL ARRAY WITH JSON DATA. 
    dispatch_async(dispatch_get_main_queue(), ^{ 
    [ai stopAnimations]; // SPINNING STOPS AFTER LONG TASK. 
    }); 
}); 
+0

Я просто попробовал свой код, но pickerview все еще пуст, а индикатор активности не вращается (но массив заполнен данными). Я сделал то, что Stonz2 заговорил, я поставил точку останова в «numberOfComponentsInPickerView», и методы pickerview выполняются, но без точки останова они не выполняются. Меня это действительно волнует. –

+0

Спасибо, Ян, на самом деле, ваш ответ сработал, с небольшой помощью Stonz2: I –

+0

Извините, я превысил ограничение на 5 минут, чтобы редактировать комментарии, я просто переключил окна и был отправлен комментарий, это комментарий: я взял " reloadAllComponents "от Stonz2 и поставить его перед« stopAnimations »кода Яна, и теперь работает код Иана. Я дам очки обоим, и ответ Яна правильный. Спасибо, приятели. –

1

Убедитесь, что ваша точка зрения сборщика dataSource и delegate установлены. После завершения веб-сервиса вам необходимо перезагрузить источник данных вашего сборщика обновленным arr.

- (void) viewDidLoad { 
[super viewDidLoad]; 
pv.dataSource = self; 
pv.delegate = self; 
[ai startAnimation]; // ACTIVITY INDICATOR STARTS SPINNING. 
[self performSelector:@selector(get_data) // FILL ARRAY. 
      withObject:nil 
      afterDelay:0]; } 

- (void) get_data { 
    // CALL WEB SERVICE, FILL ARRAY WITH JSON DATA. 
    [ai stopAnimation]; // SPINNING STOPS AFTER LONG TASK. 
    [pv reloadAllComponents]; 
} 
+0

Ничто не работает. Если я удалю функцию performSelector, функция pickerview работает отлично, так что есть что-то в функции performSelector и жизненном цикле, которые делают методы pickerview неработоспособными. –

+0

Я взял «reloadAllComponents» из Stonz2 и поместил его перед «stopAnimations» кода Яна, и теперь работает код Иана. Я дам очки обоим, и ответ Яна правильный. Спасибо, приятели. –