2010-02-16 2 views
0

나는 xmlParserNSXMLParser가 실행되는 동안 어떻게 단추를 비활성화 한 다음 완료되면 활성화 할 수 있습니까?

내가

goButton 아래 getXML 방법으로 xmlParser 클래스에 내 viewControllerNSURL 객체를 전달하고있어 버튼 내가 getXML를 호출하는 탭 클래스로 XMLParser.h을 가져 오는 viewController입니다했다 방법을 아래에. 나는 getXML 메서드를 트리거하기 위해 두드린 버튼을 비활성화했다. 그러나 xmlParser가 반환 된 XML을 구문 분석하고 나면 다시 사용할 수 있도록 코드를 어디에 넣어야할지 모르겠습니다.


- (IBAction) getXML { 
    goButton.enabled = NO; 

    // allocate and initialize the xmlParser 
    xmlParser = [[XMLParser alloc] init]; 

// then generate the URL we are going to pass to it and call the fetchXML method passing the URL. 
    NSURL *xmlurl = [[NSURL alloc] initWithString:@"http://www.mysite.com/myfile.xml"]; 
    [xmlParser fetchXMLFromURL:xmlurl]; 

    // release objects 
    [xmlurl release]; 
    [xmlParser release]; 

} 

는 @Squeegy 권고에 따라, 나는 내 코드를 수정했습니다. 파서가 구문 분석이 완료되면

2010-02-17 00:22:20.574 XMLApp[2443:521b] *** -[viewController performSelectorOnMainThread:withObject:]: unrecognized selector sent to instance 0x1285a0 
2010-02-17 00:22:20.578 XMLApp[2443:521b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[viewController performSelectorOnMainThread:withObject:]: unrecognized selector sent to instance 0x1285a0' 
2010-02-17 00:22:20.583 XMLApp[2443:521b] Stack: (
    861696817, 
    860329709, 
    861700631, 
    861203093, 
    861166272, 
    18715, 
    846004025, 
    845672609, 
    848189713 
) 
+0

나쁜, 그 방법은'- (void) performSelectorOnMainThread : (SEL) aSelector withObject : (id) arg waitUntilDone : (BOOL) wait'. 나는 대답에서 잘못된 방법 이름을 주었다. –

+0

@ 스큐 기 OK, 다소 도움이되었습니다. 지금 오류는 없지만 fetchXMLFromURL 함수는 실제로 수행 한 작업을 수행하지 않습니다. 마치 파서가 xml 파일에 대한 서버에 실제로 연결을 시작하기 전에 컨트롤이 주 스레드로 돌아가는 것과 같습니다. 스레딩이 도입되기 전에 완벽하게 작동했습니다 – conorgriffin

+0

아마 스레딩이있는 샌드 박스에서 간단한 예제를 시도해야합니다. 주위를 둘러 보는 것은 힘들 수 있습니다. 이 질문은 별도의 질문에 대한 별도의 문제 일 수 있습니다. 이 하나는 붐비는군요. –

답변

1
- (IBAction)getXML { 
    goButton.enabled = NO; 

    xmlParser = [[XMLParser alloc] init]; 
    NSURL *xmlurl = [[NSURL alloc] initWithString:@"http://www.mysite.com/myfile.xml"]; 
    [xmlParser fetchXMLFromURL:xmlurl]; 

    [self performSelectorInBackground:@selector(parseInBackground) withObject:xmlParser]; 

    [xmlurl release]; 
    [xmlParser release]; 
} 

- (void)parseInBackground:(NSXMLParser*)parser { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    [parser parse]; 
    [self performSelectorOnMainThread:@selector(didFinishXMLParsing:) 
          withObject:parser 
         waitUntilDone:NO]; 

    [pool drain]; 
} 

- (void)didFinishXMLParsing:(NSXMLParser*)parser { 
    goButton.enabled = YES; 
} 

트릭은 배경 스레드에서 처리를 수행하여 UI가 처리하도록 허용합니다. 구문 분석이 끝나면 주 스레드에서 UI를 다시 변경해야합니다.

+0

@Squeegy 감사합니다.하지만 내 질문에 대해 오해 한 것 같지만 코드를 이해하지 못합니다. 내 구문 분석 코드는 내 응용 프로그램에서 구문 분석을 위해 가져올 수있는 제네릭 클래스가되는 것이 유일한 외부 클래스에 있습니다. 필자의 파서 클래스의 헤더 파일을 내 View Controller에 임포트했으며 필자는 내 viewController 내에서 파서를 호출합니다. – conorgriffin

+0

@Squeegy 제 목표는 버튼을 비활성화하는 것입니다. 그래서 메소드는 이전 요청을 완료하기 전에 여러 번 호출 할 수 없습니다. 그래서 나는 파싱이 완료 될 때까지 사용자가 버튼을 누르는 것을 막기를 원한다. – conorgriffin

+0

이것은 그렇게합니다. 'performSelectorInBackground : withObject :'는 백그라운드 스레드에서 메소드를 실행할 수있게합니다. 주 스레드에서 UI를 업데이트 (버튼 비활성화) 할 수 있도록하는 것이 중요합니다. 앱이 반응하지만 버튼은 사용할 수 없습니다. 구문 분석이 끝나면 "Hey main thread, 나는 구문 분석을 끝냈습니다."라고 말하면 메인 스레드가 버튼을 활성화합니다. 메인 스레드 만 UI를 업데이트 할 수 있기 때문에 이것은 중요합니다. 따라서 파서 클래스는 백그라운드 스레드에서 파싱 메서드를 실행 한 다음 주 스레드에서 메서드가 완료되면이를 위임합니다. –

-1

, 그것의 대리자를 호출합니다 : :

는 라인

[self performSelectorOnMainThread:@selector(didFinishXMLParsing:) withObject:parser]; 

다음과 같이 컴파일러는 불평에 도달 할 때까지

- (IBAction) getXML { 
    goButton.enabled = NO; 

    xmlParser = [[XMLParser alloc] init]; 

    [self performSelectorInBackground:@selector(parseInBackground:) withObject:xmlParser]; 

} 

- (void)parseInBackground:(XMLParser*)parser { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    NSURL *xmlurl = [[NSURL alloc] initWithString:@"http://www.mysite.com/myfile.xml"]; 

    [parser fetchXMLFromURL:xmlurl]; 
    [self performSelectorOnMainThread:@selector(didFinishXMLParsing:) withObject:parser]; 

    [xmlurl release]; 
    [pool drain]; 

} 

- (void)didFinishXMLParsing:(NSXMLParser*)parser { 
    goButton.enabled = YES; 
} 

이 작동 같네요

- (void)parserDidEndDocument:(NSXMLParser *)parser

해당 방법에서 단추를 다시 사용할 수 있습니다. 보기를 변경해야하기 때문에 performSelectorInMainThread 호출을 사용해야합니다.

+0

@pgb가 어떻게 구현 될지 자세히 설명해 주시겠습니까? 나는 뷰를 변경하지 않고,'viewController'는 파서를 호출하는 뷰입니다. 파서가 다른 뷰에 없으므로 NSObject 인 외부 클래스에 있습니다 – conorgriffin

관련 문제