2010-07-31 1 views
0

www.example.com/number에서 읽으면 임의의 숫자를 얻습니다. 내 iPhone 앱에서는 각 요청이 완료된 후 해당 주소에서 계속해서 읽고 새 번호를 화면에 표시 할 수 있기를 원합니다. 뷰가로드되는 즉시이 프로세스를 시작한다고 가정 해 보겠습니다. 마지막으로, 부채로 웹 요청을 단순화하기 위해 ASIHTTPRequest을 사용하고 있습니다.NSTimer를 사용하지 않고 연속 배경 스레드를 사용하여 iPhone UI를 업데이트 할 수 있습니까?

접근 방식 1 : 내 viewDidLoad 메서드에서 루프에서 URL에서 동기식으로 읽을 수 있습니다 (HTTP 요청의 응답을받을 때까지 실행이 계속되지 않음). 장점 : 요청은 연속적이며 요청에 응답 할 수 있습니다. 단점 : 기능을 종료하지 않고 런타임 루프를 다시 제어하기 때문에 UI가 업데이트되지 않습니다. 분명히 이것은 좋은 해결책이 아닙니다.

접근 방식 2 : 내 viewDidLoad 메서드에서 초당 한 번 fetchURL 함수를 호출하는 타이머를 만듭니다. 장점 : 각 요청은 별도의 스레드에 있으며 각 요청이 완료되면 UI가 업데이트됩니다. 단점 : 요청은 별도의 스레드에 있으므로 제대로 제어 할 수 없습니다. 예를 들어 첫 번째 요청에 연결 시간 제한이있는 경우 오류 팝업을 표시하고 설정이 변경 될 때까지 추가 요청이 발생하지 않도록 할 수 있습니다. 그러나이 방법을 사용하면 제한 시간까지 3 초가 걸리면이 시간에 두 개의 추가 요청이 이미 시작되었습니다. 방금 타이머를 느리게하면 연결이 제대로 작동 할 때 데이터가 너무 느리게 들어옵니다.

내가 언급 한 처음 두 가지 접근법의 장점을 통합 할 수있는 접근법이있는 것처럼 보입니다. 나는 이전 요청의 결과에 따라 다음 요청을 보내지 않을지 여부를 결정할 수있는 방법을 원합니다.

접근법 3 : 나는 더 빨리 발사하는 타이머 (0.25 초마다 말하기)를 사용했지만 타이머 기능을 사용하여 다음에 무엇을 할지를 알 수있는 플래그를 확인하도록했습니다. 따라서 이전 요청이 완료되면 오류가 발생하지 않는 한 새로운 요청을 보냅니다. 그렇지 않으면 이전 요청이 완료되지 않은 경우 새 요청을 보내지 않고 타이머 기능이 반환됩니다. 이 타이머를 더 빠르게 실행하면 응답 시간이 향상되지만 깃발을 통해 원하는 동기화를 얻을 수 있습니다.

접근법 3이 내가 원하는 것을 할 것 같지만 약간의 강제력이있는 것으로 보입니다. 누구나 이것에 대한 더 나은 접근 방법에 대한 제안을 갖고 있습니까? 아니면 접근 방식 3과 같은 것이 가장 좋은 방법입니까?

+1

다른 답변은 ... ** 응용 프로그램에서 절대로 적극적으로 폴링해서는 안된다는 것을 추가하고 싶습니다. ** 그렇게하면 배터리가 소모되고 응답 성이 저하됩니다. – bbum

답변

1

저는 NSOperation이 귀하가 필요하다고 생각합니다. 위의 1 번 해결책을 사용하지만 코드를 NSOperation의 기본 메소드에 배치하십시오. 이런 식으로 뭔가 : 연산 큐 클래스를 호출 할 수 있도록

.H 파일

@interface MyRandomNumberFetcher : NSOperation { 

} 

@end 

하는 .m 파일

@implementation MyRandomNumberFetcher 

- (void) main { 
     // This is where you start the web service calls. 
} 

@end 

나는 또한 UI 컨트롤러에 대한 참조를 추가하는 것이 좋습니다 것 적절한시기에 다시.

0

다른 제안이 있습니다. 다른 스레드에서 요청을 실행할 NSOperationQueue를 만듭니다. UI 새로 고침이 필요한 경우 performSelectorOnMainThread를 호출하십시오. 요청이 완료되면 다른 요청을 작성하여 대기열에 추가하십시오. 한 번에 하나의 작업 만 실행하도록 대기열을 설정하십시오.

이렇게하면 두 가지 요청을 동시에 실행할 수 없습니다.

+0

고마워, 론! NSOperations은 새로운 것입니다. 따라서 ViewController에서 큐를 생성하고 초기 NSOperation을 추가하십시오. 작업이 실행되고 번호가 다운로드됩니다. 작업 코드에서 performSelectorOnMainThread 메시지를 ViewController 객체에 보내면됩니까? 호출 된 함수는 IBOutlet을 업데이트 할 책임이 있습니다. 그렇다면 NSOperation이 ViewController에 성공적으로 (또는 실패한) 완료되었음을 알리면 큐에 새 NSOperation을 추가하거나 추가하지 못하게 할 수 있습니까? – jmac

+0

@NWCoder. 당신이 묘사 한대로. 그러나 @Mo 제안을 확인하는 것이 좋습니다. 오늘은 GCD를 직접보고있었습니다. –

2

적은 코드로 더 적은 리소스를 사용하여 GCD를 사용하여이 작업을 수행 할 수 있습니다.이것은 당신이 그것을 할 수있는 방법입니다 : 동기 호출로

  1. 로드 데이터와 실패한 경우 시간 제한을 처리 : 다음을 수행

    viewDidLoad에서 호출 비동기 (dispatch_async 사용) 블록.

  2. 성공한 경우 기본 스레드에 UI 업데이트를 알리십시오.
  3. 동일한 작업을 수행하는 지연 후 (dispatch_after 사용) 새 블록을 실행하도록 대기열에 넣습니다. ,
  4. 그렇지 않으면 블록에서 사용자 정의보기를 업데이트하려면

    1. , 사용자가 설정할 수 setNeedsDisplay :

    내가 이러한 방법을 생각할 수있는 또 다른 스레드에서 메인 스레드로 다시 호출하려면 주 스레드에서 실행중인 대기열 인 "주 대기열"에 블록을 대기시킬 수 있습니다. 을 호출하여 대기열을 가져옵니다. 다른 대기열과 같이 처리하십시오 (예 : dispatch_async을 호출하여 블록을 추가 할 수 있음).

  5. 블록을 사용하지 않으려면 NSObjectperformSelectorOnMainThread:withObject:waitUntilDone: 메소드를 사용할 수 있습니다.

자세한 내용은 GCD Reference을 참조하십시오.

즉 게임 데이터 등을 가져 오는 것과 같은 특정 작업을 제외하고는 자주 작은 요청을 자주해서는 안됩니다. 안테나가 수면 상태를 유지하도록하여 배터리 수명을 심각하게 줄입니다.

+0

고마워, 모! GCD는 나를위한 새로운 주제이기도합니다. 그래서 나는 그것에 대한 연구를 할 것입니다. 프로세스가 의미있는 것 같지만 2 단계를 명확히 할 수 있습니까? 블록이 메인 쓰레드로 알림을 전송하는 방법은 무엇입니까? – jmac

+0

업데이트 된 답변보기 희망이 도움이됩니다. – mohsenr

관련 문제