2014-06-18 4 views
0

인터넷에서 가져온 화면에 이미지를 표시하고 싶습니다. 나는 NSURLConnection을 사용하여 비동기 호출을 만들어 데이터를 가져 왔으며 응답 블록에서 코드를 호출하여 UIImage 객체에 할당했습니다.iOS : NSURLConnection sendAsynchronousRequest 이후에 sleep (1)을 사용해야하는 이유는 무엇입니까?

내 질문에 왜 블록 실행 후 sleep (1)을 호출해야합니까? 전화하지 않으면 내 이미지가 화면에 그려지지 않습니다. 이것을 이루기위한 또 다른, 우아한 방법입니까?

-(void)loadImage:(NSString *)url 
{ 
    NSURL *imageURL = [NSURL URLWithString:url]; 
    NSOperationQueue *queue = [[NSOperationQueue alloc]init]; 
    NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageURL cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5.0f]; 
    [NSURLConnection sendAsynchronousRequest:imageRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { 
     if(!connectionError) { 
      if(data) { 
       //there goes the main thingy 
       self.myView.wallpaperImage = [UIImage imageWithData:data]; 
       [self.myView setNeedsDisplay]; 
      } else { 
       NSLog(@"No data found at url:%@",url); 
      } 
     } else { 
      NSLog(@"Could not connect to %@",url); 
     } 
    }]; 
    sleep(1); 
} 
+3

'sleep()'을 호출하지 마십시오. – zaph

+0

어쩌면 내가 잘못된 방법으로 묻고 있었을 수도 있습니다 ... 나는 그것을 부르지 않아도된다는 것을 알고 있지만, 그렇지 않다면 나는 흰 화면을 얻었습니다. 내가 잠을 자면 문제없이 이미지가 그려집니다. – Bogdan

+4

모든 UIKit 호출이 기본 대기열에서 수행되는지 확인하십시오. – Jiri

답변

2

이 :

self.myView.wallpaperImage = [UIImage imageWithData:data]; 
[self.myView setNeedsDisplay]; 

가 NSOperationQueue에 의해 관리되는 스레드에서 일어나고은 sendAsynchronousRequest에 전달. 이러한 메서드는 주 스레드에서 호출해야합니다. 잠자기로 인해 주 스레드의 런 루프가 반복적으로 실행 된 후 해당 통화가 작동 한 것으로 보입니다. 이 문제를 해결하려면, 그리고 현재의 접근 방식은있을 것이다 다른 문제의 전체 무리를 피하려면 다음을 수행하십시오

[NSURLConnection sendAsynchronousRequest:imageRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { 
     if([data length] > 0) { 
      //there goes the main thingy 
      [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
       self.myView.wallpaperImage = [UIImage imageWithData:data]; 
       [self.myView setNeedsDisplay]; 
      }]; 
     } else { 
      // Perform your error handling here. 

     } 
    }]; 

이 메인 큐에서 호출 UIKit들을 수행 할 [NSOperationQueue mainQueue]를 사용합니다 - libdispatch 없습니다. libdispatch는 낮은 수준의 인터페이스입니다. 항상 높은 수준의 인터페이스 (이 경우에는 NSOperationQueue)를 사용하는 것이 좋습니다. UIKit은 주 스레드 (또는 대기열)에서 호출 할 때만 안전합니다. 에 대한 bestpractices을 따르는 오류 처리 동작을 변경합니다. 호출 결과 (이 경우 데이터)를 확인한 다음 반환 된 오류를 처리합니다.

코드는 실제로 블록이 캡처 된 객체 (이 경우 자체)를 유지하는 이유의 좋은 예입니다. 여기에 유지주기가 없으면 ARC는 범위를 벗어나 자마자 queue을 파괴 할 수 있으며 블록은 실행되지 않습니다. 대신 유지주기 때문에 대기열은 블록이 실행될 때까지 계속 남아 있습니다.

+0

자세한 설명을 해 주셔서 감사합니다. – Bogdan