저는 일반적으로 Objective C 및 iOS 개발에 익숙하지 않습니다. http 요청을 만들고 레이블에 내용을 표시하는 응용 프로그램을 만들려고합니다.NSURLSessionDataTask가 돌아 오기를 기다리십시오.
테스트를 시작했을 때 로그에 데이터가 있다는 것을 나타 냈지만 레이블이 비어 있다고 나타났습니다. 분명히 이것은 라벨 텍스트가 업데이트 될 때 응답이 준비되지 않았기 때문에 발생합니다.
이 문제를 해결하기 위해 상단에 루프를 달았지만이 문제를 해결할 더 좋은 방법이 있어야합니다.
ViewController.m
- (IBAction)buttonSearch:(id)sender {
HttpRequest *http = [[HttpRequest alloc] init];
[http sendRequestFromURL: @"https://en.wiktionary.org/wiki/incredible"];
//I put this here to give some time for the url session to comeback.
int count;
while (http.responseText ==nil) {
self.outputLabel.text = [NSString stringWithFormat: @"Getting data %i ", count];
}
self.outputLabel.text = http.responseText;
}
HttpRequest.h
#import <Foundation/Foundation.h>
@interface HttpRequest : NSObject
@property (strong, nonatomic) NSString *responseText;
- (void) sendRequestFromURL: (NSString *) url;
- (NSString *) getElementBetweenText: (NSString *) start andText: (NSString *) end;
@end
HttpRequest.m
@implementation HttpRequest
- (void) sendRequestFromURL: (NSString *) url {
NSURL *myURL = [NSURL URLWithString: url];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: myURL];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest: request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
self.responseText = [[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding];
}];
[task resume];
}
덕분에 많은 매우 유용한 의견을 많이 읽은 후 도움말 :
업데이트
여기 제가 요점을 잃어버린 것을 깨달았다. 따라서 기술적으로 NSURLSessionDataTask는 비동기 적으로 호출을 할 대기열에 작업을 추가 한 다음 작업에서 생성 된 스레드가 완료되면 실행하려는 코드 블록과 함께 해당 호출을 제공해야합니다.
Duncan은 응답과 코드 주석에 많은 감사를드립니다. 그 점이 나를 이해하는 데 많은 도움이되었습니다.
제공된 정보를 사용하여 절차를 다시 작성했습니다. 그것들은 약간 장황하다. 그러나 나는 그것이 지금 전체 개념을 이해하는 것을 원했다.
HttpRequest.m
- (void) sendRequestFromURL: (NSString *) url
completion:(void (^)(NSString *, NSError *))completionBlock {
NSURL *myURL = [NSURL URLWithString: url];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: myURL];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest: request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//Create a block to handle the background thread in the dispatch method.
void (^runAfterCompletion)(void) = ^void (void) {
if (error) {
completionBlock (nil, error);
} else {
NSString *dataText = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
completionBlock(dataText, error);
}
};
//Dispatch the queue
dispatch_async(dispatch_get_main_queue(), runAfterCompletion);
}];
[task resume];
}
ViewController.m이
- (IBAction)buttonSearch:(id)sender {
NSString *const myURL = @"https://en.wiktionary.org/wiki/incredible";
HttpRequest *http = [[HttpRequest alloc] init];
[http sendRequestFromURL: myURL
completion: ^(NSString *str, NSError *error) {
if (error) {
self.outputText.text = [error localizedDescription];
} else {
self.outputText.text = str;
}
}];
}
내 새로운 코드에 대한 의견을 보내 주시기 바랍니다 (내가 그들을 중첩보다는 코드 블록을 선언하고있다). 스타일, 잘못된 사용법, 잘못된 흐름; 피드백은 학습의이 단계에서 매우 중요하므로 더 나은 개발자가 될 수 있습니다.
다시 한번 답장을 보내 주셔서 감사합니다.
'dataTaskWithRequest' 호출에서 제공하는 완료 핸들러 블록을 사용해야한다. 블록을'sendRequestFromURL'의 매개 변수에 완성 블록으로 추가하고, 요청이 끝났을 때 그 블록을 호출하십시오. 블록에서 레이블을 업데이트하기위한 코드를 작성하십시오 – luk2302