“[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]”使得 UI 无响应

"[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]" makes the UI non response

UIViewController viewDidAppear 事件中,我想从网络服务中获取一些数据。代码如下:

- (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;
}

当运行进入[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];时,请求成功块将不会执行,UI变为无响应。

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

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

不要使用那种语法

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

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

除此之外,您还告诉当前 运行ning 运行UIApplication 循环到 运行 阻止它。

做这样的事情

- (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];
  }
}

代码不考虑在后台线程中响应 returns 的潜在问题。