앱을 만들때 데이터를 처리해야하는 경우가 생길 수 밖에없다. 보통은 통신을 하거나, 주소록을 긁어오거나 하는 등의 작업이 그것인데 무작정 해당 기능을 구현하다보면 화면이 프리징 되어버리는 문제에 부딪히게 된다.

 예컨데 특정 데이터를 연속적으로 읽어오는데 동시에 Progressbar를 증가시키려고 한다면 


데이터 처리 -> Progress 값 증가 -> 데이터 처리 -> Progress 값 증가  

 

 위와 같이 의도한대로 작동하는게 아니라 데이터처리가 끝날때까지 Progressbar는 멈춰있다가 처리가 끝날때 한번에 애니메이션이 발생한다. 즉, 값은 전달되지만 화면처리가 정상적으로 이뤄지지 않는것이다. 이런 경우 스레드를 분류해줄 필요가 생긴다. 개념적으로는 아래와 같다 



-(void)viewDidLoad{
    // 화면이 불러왔을때 바로 실행하는 경우 
    [self performSelectorInBackground:@selector(dataReceive) withObject:nil];
}

-(void)dataReceive{
    // 데이터 처리 

    // 값으로 넘겨줄 NSNumber객체 생성 
    NSNumber *obj = [NSNumber numberWithFloat:0.1];
    [self performSelectorOnMainThread:@selector(increaseProgress:) withObject:obj waitUntilDone:TRUE];
    NSLog(@"데이터 처리 at %@",[NSThread CurrentThread]);
}

-(void)increaseProgress:(NSNumber *)progVal{
    // NSProgressBar타입의 prog라는 객체가 있다고 가정 
    [[self prog] setProgress:[progVal floatValue] animated:TRUE];
    NSLog(@"화면처리 at %@",[NSThread CurrentThread]);
}

 위와같이 처리해주면, 화면처리와 데이터 처리를 병렬적으로 보이게 처리할 수 있다. 이때 기본적으로 performSelectorOnMainThread등의 셀렉터를 이용한 함수들은 리턴값을 가지지 않아 함수에서 반환값을 뽑아오지는 못한다. 아마 많은 사람들이 BOOL값 정도는 받아와서 해당 작업이 완료되었는지 체크하려고 할 터이다.

 그럴때는 return값을 받아올 객체의 주소값을 넘기면 변경된 데이터를 가지고 올 수 있긴하나, 그 방법은 좀 더 복잡하니 후에 다루도록 하겠다. 

+ Recent posts