Настройка UIActivityIndicatorView во время подготовки представления - PullRequest
1 голос
/ 15 мая 2010

У меня есть UITabbBarController с UITableView. При определенных обстоятельствах набор данных TabBarControllers требует обновления, когда пользователь приходит из другого представления,

например. начальная загрузка при первом вызове TabBarController или при изменении настроек.

Это обновление набора данных занимает около 2 секунд, и я хочу показать UIActivityIndicatorView.

Проблема в том, что когда я вхожу из другого представления, я не знаю, к какому виду его прикрепить, поскольку загрузка tabbarController выполняется в методе viewWillAppear.

Есть какие-нибудь подсказки, как я могу это сделать?

1 Ответ

1 голос
/ 15 мая 2010

Я делал подобные вещи в методе viewDidAppear. Мой код запускает фоновую задачу для загрузки данных из URL. Он также передает фоновой задаче селектор метода для вызова контроллера, когда это будет сделано. Таким образом, контроллер уведомляется о том, что данные были загружены и могут обновляться.

Я не знаю, является ли это лучшим способом сделать это, но пока у меня все работает нормально: -)

Чтобы дать более подробную информацию, в дополнение к селектору метода для вызова, когда фоновая задача загрузила данные, я также и он - селектор метода на контроллере, который выполняет загрузку. Таким образом, фоновая задача управляет происходящим, но контроллер представления предоставляет специфический для данных код.

Вот вид ViewDidAppear код:

- (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, содержащий индикатор активности.

BackgroundTask.m выглядит так:

@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% прозрачный синий фон с индикатором активности в середине. Для него есть контроллер с таким кодом:

@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

Да, это помогает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...