0

在我的应用程序的某个时刻,我列出了需要应用程序从服务器获取数据的代码列表,我知道这个过程可能需要相当长的时间,我决定在屏幕变暗的地方放置一个加载通知,并在它的中心说“现在从服务器加载 blablabla 数据”

问题是,在从服务器加载多个数据(JSON 数据)之间,即使我在 JSON 函数之间放置代码来更改它,标签也不会改变

这是我的代码

[self.viewReportProduksi getDataReport];
                           [loadinglabel setText:@"Loading Chart Data from server . . ."];
                           [self.viewReportProduksi getChartData];
                           [loadinglabel setText:@"Loading Data Komisi from server . . ."];
                           [self.viewKomisi getDataKomisi];
                           [loadinglabel setText:@"Loading Bonus Data from server . . ."];
                           [self.viewBonus getDataBonus];
                           [loadinglabel setText:@"Loading Bonus Agen Data from server . . ."];
                           [self.viewBonusAgen getDataBonusAgen];
                           [loadinglabel setText:@"Loading Agent Reward Data from server . . ."];
                           [self.viewAgenReward getDataRewardAgen];

那些“getXXXXXX”是执行 JSON 的方法。

从逻辑上讲,这应该使应用程序显示进度走了多远。但标签一直停留在“从服务器加载图表数据”,并且不会根据我的代码进行相应更改。

我在主线程和使用dispatch_queue都试过这个,两者都没有区别

谢谢

4

3 回答 3

1

这是因为您在主线程上加载数据,并且由于主线程非常繁忙,它永远不会更新显示。

您需要将数据加载移动到另一个线程,例如,向主线程发送带有更新信息的通知。

于 2012-05-10T07:19:34.760 回答
1

问题是所有图形更新都发生在主线程上。因此,在整个代码块完成之前,显示屏上不会发生任何变化。我认为这是您需要在后台进行所有数据加载的情况。为了获得最大的灵活性,我会使用大量的NSBlockOperations

首先,您需要一个在主线程上运行的方法来更新您的状态文本。

-(void) updateStatusWithString: (NSString*) message
{
    [loadingLabel setText: message];
    // might want to do other stuff e.g. if you have fully loaded the data
}

然后,代替您的方法顺序加载所有数据,为每个阶段创建一个 NSBlockOperation 并将其放入操作队列中。

-(void) loadData
{
    NSBlockOperation* block1 = [NSBlockOperation blockOperationWithBlocK: ^()
    {
        [self performSelectorOnMainThread: @selector(updateStatusWithString:)
                               withObject: @"Loading chart data from server"
                            waitUntilDone: NO];
        [self.viewReportProduksi getChartData];
    }];
    NSOperationQueu* queue = [[NSOperationQueue alloc] init];
    [queue addOperation: block1];

    NSBlockOperation* block2 = [NSBlockOperation blockOperationWithBlocK: ^()
    {
        [self performSelectorOnMainThread: @selector(updateStatusWithString:)
                               withObject: @"Loading Data Komisi from server"
                            waitUntilDone: NO];
        [self.viewKomisi getDataKomisi];
    }];
    [block2 addDependency: block1];
    [queue addOperation: block2];

    // etc for all the other blocks
}

因为每个操作都依赖于前一个操作,所以它们会一个接一个地执行,但是在某个后台线程上。使用操作和操作队列比 GCD 更有优势,因为

  • 您可以使用以下方法轻松建模操作之间的依赖关系-addDependency:
  • 操作有一个内置的取消机制。如果用户决定中途退出应用程序,您可以发出

    [queue cancelAllOperations];
    

    队列上所有尚未开始的操作都将被取消。

于 2012-05-10T09:03:30.363 回答
0

我认为你应该这样做:

 - (void)firstPart {
    //This is main thread
    [loadinglabel setText:@"Loading Chart Data from server . . ."];
    [NSThread detachNewThreadSelector:@selector(getChartData) toTarget:self.viewReportProduksi withObject:nil];
}

 - (void)getChartData {
    //this is an extra thread
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    //Your loading code
    [self performSelectorOnMainThread:@selector(secondPart) withObject:self waitUntilDone:NO];
    [pool drain];
 }
 - (void)secondPart {
        [loadinglabel setText:@"Loading Data Komisi from server . . ."];
        [NSThread detachNewThreadSelector:@selector(getDataKomisi) toTarget:self.viewKomisi withObject:nil];
}

等等...

于 2012-05-10T08:19:50.430 回答