У меня есть UILabel и UIProgressView, для которых я даю несколько обновлений, но ничего не отображается, пока мой объект связи не будет завершен.UILabel и UIProgressView не обновляются до тех пор, пока мой класс связи не завершится
Я получил эту ViewController:
@interface UpdateServerViewController : UIViewController <TaskController> {
AgentAssetManager * agentAssetManager;
}
@property (strong, nonatomic) IBOutlet UIButton * updateNowButton;
@property (strong, nonatomic) IBOutlet UILabel * statusLabel;
@property (strong, nonatomic) IBOutlet UILabel * lastUpdateSuccessTimeLabel;
@property (strong, nonatomic) IBOutlet UILabel * lastUpdateAttemptTimeLabel;
@property (strong, nonatomic) IBOutlet UILabel * lastUpdateResultLabel;
@property (strong, nonatomic) IBOutlet UIProgressView * progressView;
- (IBAction) updateNow:(id) sender;
- (void) updateLabels;
- (void) scheduleInNextRunloopSelector:(SEL)selector;
- (void) taskSetStatus:(NSString *)status;
- (void) taskFinishedSuccessfully;
- (void) taskFinishedUnSuccessfully;
@end
Метод updateNow вызывает AgentAssetManager:
[self scheduleInNextRunloopSelector:@selector(updateTime:)];
McDbg(m, d+1, @"Calling AgentAssetManager sendToServer");
// [statusLabel setText:@"Contacting Server"];
[agentAssetManager sendToServer:true taskController:self];
AgentAssetManager sendToServer это выполняет ряд шагов, и отправляет уведомления обратно UpdateServerViewController по протоколу TaskController :
- (void) sendToServer:(Boolean) notifyUser
taskController:(id<TaskController>) taskCtlr
{
char * m = "AgentAssetManager.sendToServer";
int d = 0;
int steps = 6; // Total number of steps
McDbg(m, d, @"Send Asset data to server");
McDbg(m, d+1, @"Notify User about status/errors=%s",
(notifyUser) ? "YES" : "NO");
if (taskCtlr != nil) {
[taskCtlr taskSetProgress:(float)1/(float)steps];
[taskCtlr taskSetStatus:@"Checking if server is reachable"];
}
McDbg(m, d+1, @"SLEEPING");
sleep(5); // XXX tmp debug
ServerStatusManager *statusMgr = [[ServerStatusManager alloc] init];
Boolean ready = [statusMgr isServerReady];
McDbg(m, d+1, @"Server Status ready=%s", (ready) ? "YES" : "NO");
if (!ready) {
NSString *msg = @"Server could not be reached";
McLogWarn(m, @"Server Not ready %@", [statusMgr serverUrlBase]);
[self updateResult:false];
if (notifyUser)
[McUiError showMessage:msg];
if (taskCtlr) {
[taskCtlr taskSetStatus:msg];
[taskCtlr taskFinishedUnSuccessfully];
}
return;
}
McDbg(m, d+1, @"Getting Asset data");
if (taskCtlr != nil) {
[taskCtlr taskSetProgress:(float)2/(float)steps];
[taskCtlr taskSetStatus:@"Gathering data"];
}
... etc ....
Вот UpdateServerViewController taskSetProgress и taskSetStatus:
- (void) taskSetStatus:(NSString *) status
{
char * m = "UpdateServerViewController.taskSetStatus";
int d = 0;
McDbg(m, d, @"Status=<%@>", status);
[statusLabel setText:status];
McDbg(m, d+1, @"Finished");
}
- (void) taskSetProgress:(float) percent
{
[progressView setHidden:false];
[progressView setProgress:percent animated:YES];
}
Выход отладки ясно показывает, что UpdateServerViewController taskSetProgress и taskSetStatus называются, когда они предполагают, чтобы. Проблема в том, что новые значения набора не вступают в силу до тех пор, пока не будет завершен весь метод agentAssetManager.updateNow.
Основываясь на результатах поиска на этом сайте для подобных проблем UILabel я добавил метод таймера:
- (void) scheduleInNextRunloopSelector:(SEL)selector
{
char * m = "UpdateServerViewController.scheduleInNext";
int d = 0;
McDbg(m, d, @"Starting");
NSDate *fireDate = [[NSDate alloc] initWithTimeIntervalSinceNow:0.5]; // 500 ms
NSTimer *timer = [[NSTimer alloc]
initWithFireDate:fireDate interval:0.5 target:self
selector:selector userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}
- (void)updateTime:(NSTimer *)timer
{
char * m = "UpdateServerViewController.updateTime";
int d = 0;
McDbg(m, d, @"Starting");
[statusLabel setText:@"XXX Timer called"];
}
Проблема заключается в то же самое с или без таймера. С помощью таймера отладка показывает, что таймер запланирован до вызова agentAssetManager.updateNow, но метод updateTime не вызывается до тех пор, пока не завершится действие agentAssetManager.updateNow. Это даже со сном (5) в updateNow, чтобы попытаться избежать состояния гонки нитей.
Отладка показывает, что все средства UpdateServerViewController и AssetAgentManager работают в потоке 1. Я не делаю никаких NSRunLoop, кроме указанного выше таймера.
Должно быть, я пропустил что-то основное. Любая помощь будет действительно оценена!
Что вы используете, чтобы сделать реальную связь между сервером? Если вы используете какой-либо из методов ___withContentsOfURL, они заблокируют основной поток, и никаких обновлений пользовательского интерфейса не произойдет. – jsd
Я использую RestKit для связи с сервером. –