我有一种从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];
}
答案 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)
确保您的选择器视图dataSource
和delegate
已设置。 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];
}