2015-09-11 81 views
0

UIViewControllerviewDidAppear事件中,我想从Web服务获取一些数据。而这样的代码:“[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]”使UI无响应

- (void)viewDidAppear:(BOOL)animated 
{ 
[super viewDidAppear:animated]; 
NSArray *arr = [self getCarList]; 
} 

- (NSArray *)getCarList 
{ 
if (!carList) { 

    ARequset *req = [[ARequset alloc] init]; 
    [NetService sendRequest:req respClass:[Resp class] success:^(BaseResponse *response) 
    { 
     //after finished 
     self.requestFinished = YES; 
    } fail:^(NSInteger errcode, NSString *errmsg) { 
     self.requestFinished = YES; 
    }]; 
    while (!self.requestFinished) { 
     [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
    } 
} 
return carList; 
} 

时至​​运行请求成功块将不被执行,并且UI变得没有反应。

但如果我改变这样的- (void)viewDidAppear:(BOOL)animated,一切顺利。

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 
    [self performSelector:@selector(getCarList) withObject:self afterDelay:1]; 
} 

回答

3

不要做那种语法

NetService请求以异步方式工作的,该请求的结果在块传递 。您必须处理BaseResponse对象并更新您的UI或任何您想要对数据执行的操作。

轮询是坏习惯,不必要地消耗系统资源。

除此之外,您正在告诉当前正在运行的UIApplication的runloop运行哪个块。

做这样的事情

- (void)getCarList 
{ 
if (!carList) { 

    ARequset *req = [[ARequset alloc] init]; 
    [NetService sendRequest:req respClass:[Resp class] success:^(BaseResponse *response) 
    { 
     //after finished 
     self.carList = [self doSomethingWithTheResponse:response]; 
     dispatch_async(dispatch_get_main_queue(), ^(void) { 
     // Update UI 
     }); 

    } fail:^(NSInteger errcode, NSString *errmsg) { 
     dispatch_async(dispatch_get_main_queue(), ^(void) { 
     // show alert 
     }); 
     }]; 
    } 
    } 
} 

编辑:或者使用委托状的图案来处理异步行为。

取而代之的是同步方法的

- (void)methodToGetCarList 
{ 
    NSArray *cars = [self getCarList]; 
    [self doSomethingWithCars:cars]; 
} 

使用本

- (void)methodToGetCarListAsynchronously 
{ 
    [self getCarList]; 
} 

和委托方法

- (void)didReceiveCars:(NSArray *)cars errorMessage:(NSString *)error 
{ 
    if (error) { 
    // do error handling 
    } else { 
    [self doSomethingWithCars:cars]; 
    } 
} 

getCarList方法看起来像

- (void)getCarList 
{ 
    if (!carList) { 

    ARequset *req = [[ARequset alloc] init]; 
    [NetService sendRequest:req respClass:[Resp class] success:^(BaseResponse *response) 
    { 
     //after finished 
     self.carList = [self doSomethingWithTheResponse:response]; 
     [self didReceiveCars:self.carList errorMessage:nil]; 

    } fail:^(NSInteger errcode, NSString *errmsg) { 
     [self didReceiveCars:nil errorMessage:errmsg]; 
     }]; 
    } 
    } else { 
    [self didReceiveCars:self.carList errorMessage:nil]; 
    } 
} 

如果响应在后台线程中返回,代码不会考虑潜在问题。

+0

但是,getCarList方法位于单例类中。我想用一个单例来保存cardList。是卡列表不是零,直接返回,否则请求从服务器返回。 @vadian – bohan

+0

我编辑帖子向你展示另一种方式 – vadian

+0

呵呵你一脸(非常感谢)@vadian – bohan