如何用数据填充选择器视图并同时运行活动指示器?

时间:2015-01-23 21:06:07

标签: ios objective-c uipickerview performselector

我有一种从Web服务加载数据并填充数组的方法,它工作正常(让我们称之为" get_data")。我使用这个数组(" arr")作为选择器视图的数据源(" 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];
}

2 个答案:

答案 0 :(得分: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];放在那里。

如果不是这种情况,并且您正在同时调用Web服务以获取主线程上的数据(不执行主线程上的阻塞网络操作),则可以改为这一切都是背景线程:

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

答案 1 :(得分:1)

确保您的选择器视图dataSourcedelegate已设置。 Web服务完成后,您需要使用更新的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];
}