Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何用数据填充pickerview并同时运行活动指示器?_Ios_Objective C_Uipickerview_Performselector - Fatal编程技术网

Ios 如何用数据填充pickerview并同时运行活动指示器?

Ios 如何用数据填充pickerview并同时运行活动指示器?,ios,objective-c,uipickerview,performselector,Ios,Objective C,Uipickerview,Performselector,我有一个从web服务加载数据并填充数组的方法,它工作得很好(我们称之为“get_data”)。我使用这个数组(“arr”)作为picker视图(“pv”)的数据源,它也可以正常工作,当我运行我的应用程序时,pickerview中充满了项目。有一天我决定使用“活动指示器”(“ai”),而现在“pv”总是空的,我不知道如何修复它。下面是我的代码: - (void) viewDidLoad { [super viewDidLoad]; [ai startAnimation]; // ACTIVITY

我有一个从web服务加载数据并填充数组的方法,它工作得很好(我们称之为“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会工作,但activity indicator不会:

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

当您使用
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.
}

如果您的web服务在不同的线程或块中执行,并且允许您附加一个完成响应程序,那么您应该将
[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.
  });
});

确保已设置选择器视图的
数据源
委托
。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];
}

尝试在任何选择器数据源方法中设置断点,以查看它们是否在web服务完成和活动指示器停止后被命中。并确保
arr
包含您认为它包含的对象。亲爱的Stonz2,我按照您的建议做了,arr中充满了数据,但是pickerview方法根本不执行。我刚刚尝试了您的代码,但是pickerview仍然为空,并且活动指示器没有旋转(但是数组中充满了数据)。我按照Stonz2的建议做了,我在“numberOfComponentsInPickerView”中放了一个断点,pickerview方法被执行,但是如果没有断点,它们就不会执行。这真的吓坏了我。谢谢你,伊恩,事实上,你的答案起作用了,在Stonz2的帮助下:ISorry,我超过了编辑评论的5分钟限制,我刚切换了窗口,评论就被发送了,这是评论:我从Stonz2获取了“reloadAllComponents”,并将其放在伊恩代码的“stopAnimations”之前,现在伊恩的代码起作用了。我会给两个分数,伊恩的答案是正确的。谢谢,伙计们,好像什么都没用。如果我删除performSelector,pickerview工作得很好,因此performSelector和生命周期的某些方面使得pickerview方法无法工作。我从Stonz2中选择了“reloadAllComponents”,并将其放在Ian代码的“stopAnimations”之前,现在Ian的代码可以工作了。我会给两个分数,伊恩的答案是正确的。谢谢,朋友们。