在准备好视图时设置 UIActivityIndicatorView [英] Setting UIActivityIndicatorView while view is prepared
问题描述
我有一个带有 UITableView 的 UITabbBarController.在某些情况下,当用户从另一个视图到达时,TabBarControllers 数据集需要更新,
I have a UITabbBarController with a UITableView. Under certain circumstances the TabBarControllers dataset requires updating when a user arrives from another view,
例如第一次调用 TabBarController 或更改设置时的初始加载.
e.g. the initial load when the TabBarController is called the first time, or when the settings are changed.
这个数据集更新大约需要 2 秒,我想显示一个 UIActivityIndicatorView.
This dataset update takes about 2 seconds and I want to show an UIActivityIndicatorView.
问题是当我从另一个视图进入时,我不知道将它附加到哪个视图,因为 tabbarController 的加载是在 viewWillAppear 方法中进行的.
Trouble is that when I enter from another view I don't know which view to attach it to, since the loading of the tabbarController is carried out in the viewWillAppear method.
有什么线索可以解决这个问题吗?
Any clues how I can go about this?
推荐答案
我在 viewDidAppear 方法中做过这样的事情.我的代码启动后台任务以从 url 加载数据.它还为后台任务提供一个方法选择器,以便在完成后在控制器上调用.这样控制器就会收到数据已经下载并且可以刷新的通知.
I've done this sort of thing in the viewDidAppear method. My code kicks off a background task to load the data from a url. It also hands the background task a selector of a method to call on the controller when it is done. That way the controller is notified that the data has been downloaded and can refresh.
我不知道这是否是最好的方法,但到目前为止它对我来说很好:-)
I don't know if this is the best way to do this, but so far it's working fine for me :-)
为了提供更多详细信息,除了后台任务加载数据时调用的方法的选择器之外,我还将它作为控制器上进行加载的方法的选择器.这样后台任务管理正在发生的事情,但视图控制器提供数据特定的代码.
To give some more details, in addition to the selector of the method to call when the background task has loaded the data, I also and it a selector of a method on the controller which does the loading. That way the background task manages whats going on, but the view controller provides the data specific code.
这是 viewDidAppear 代码:
Here's there viewDidAppear code:
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (reloadData) {
BackgroundTask *task = [[BackgroundTask alloc] initWithMethod:@selector(loadData) onObject:self];
task.superView = self.view.superview;
task.notifyWhenFinishedMethod = @selector(loadFinished);
[task start];
[task release];
}
}
后台任务有一个可选的 superView,因为它会向其中添加一个包含活动指示器的新 UIView.
The background task has an optional superView because it will add a new UIView to it containing an activity indicator.
BackgroundTask.m 看起来像这样:
BackgroundTask.m looks like this:
@implementation BackgroundTask
@synthesize superView;
@synthesize longRunningMethod;
@synthesize notifyWhenFinishedMethod;
@synthesize obj;
- (BackgroundTask *) initWithMethod:(SEL)aLongRunningMethod onObject:(id)aObj {
self = [super init];
if (self != nil) {
self.longRunningMethod = aLongRunningMethod;
self.obj = aObj;
}
return self;
}
- (void) start {
// Fire into the background.
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(execute:)object:nil];
thread.name = @"BackgroundTask thread";
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskFinished:) name:NSThreadWillExitNotification object:thread];
[thread start];
[thread release];
}
- (void) execute:(id)anObject {
// New thread = new pool.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (self.superView != nil) {
busyIndicatorView = [[BusyIndicator alloc] initWithSuperview:self.superView];
[busyIndicatorView performSelectorOnMainThread:@selector(addToSuperView)withObject:nil waitUntilDone:YES];
}
// Do the work on this thread.
[self.obj performSelector:self.longRunningMethod];
if (self.superView != nil) {
[busyIndicatorView performSelectorOnMainThread:@selector(removeFromSuperView)withObject:nil waitUntilDone:YES];
}
[pool release];
}
- (void) taskFinished:(NSNotification *)notification {
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSThreadWillExitNotification object:notification.object];
[self performSelectorOnMainThread:@selector(notifyObject)withObject:nil waitUntilDone:NO];
}
- (void) notifyObject {
// Tell the main thread we are done.
if (self.notifyWhenFinishedMethod != nil) {
[self.obj performSelectorOnMainThread:self.notifyWhenFinishedMethod withObject:nil waitUntilDone:NO];
}
}
- (void) dealloc {
self.notifyWhenFinishedMethod = nil;
self.superView = nil;
self.longRunningMethod = nil;
self.obj = nil;
[super dealloc];
}
@end
最后,正如我所说,我设置了一个活动指示器.我有一个 xib,它包含一个 50% 透明的蓝色背景,中间有一个活动指示器.它有一个控制器,其中包含以下代码:
Finally as I said I put up a activity indicator. I have a xib which contains a 50% transparent blue background with an activity indicator in the middle. There is a controller for it which has this code:
@implementation BusyIndicator
@synthesize superView;
@synthesize busy;
- (BusyIndicator *) initWithSuperview:(UIView *)aSuperView {
self = [super initWithNibName:@"BusyIndicator" bundle:nil];
if (self != nil) {
self.superView = aSuperView;
}
return self;
}
- (void) addToSuperView {
// Adjust view size to match the superview.
[self.superView addSubview:self.view];
self.view.frame = CGRectMake(0,0, self.superView.frame.size.width, self.superView.frame.size.height);
//Set position of the indicator to the middle of the screen.
int top = (int)(self.view.frame.size.height - self.busy.frame.size.height) / 2;
self.busy.frame = CGRectMake(self.busy.frame.origin.x, top, self.busy.frame.size.width, self.busy.frame.size.height);
[self.busy startAnimating];
}
- (void) removeFromSuperView {
[self.busy stopAnimating];
[self.view removeFromSuperview];
}
- (void) dealloc {
self.superView = nil;
[super dealloc];
}
@end
希望这会有所帮助.
这篇关于在准备好视图时设置 UIActivityIndicatorView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!