2015-09-11 74 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