2013-08-11 1 views
1

저는 현재 내 스토리 보드에 두 개의 UIImageView을 가지고 있는데 그 중 하나는 내 Facebook 프로필 사진을 다운로드하고 다른 하나는 친구 프로필 사진을 다운로드합니다. 이미지를 다운로드하는 NSURLConnectionDataDelegate 메소드 호출은 가끔씩 만 작동합니다.

Storyboard layout

는하지만, 내 문제는이 예상로 작동하는 시간의 60 % 만, 내 자신의 프로필 사진이 표시되는 시간의 다른 40 %는 내 친구의 사진 하단에 표시해야하는 위치 동안이다 , 상단 상자는 비어 있습니다. 이 결과가 다운로드 또는 완료 될 때 NSURLConnectionDataDelegate 메서드라고 부르는 결과인지 또는 Facebook에 요청 된 내 요청의 특성인지 여부가 확실하지 않습니다.

내가 viewDidLoad 페이스 북에 내 두 요청의 압축 된 버전을 붙여 넣은

, 내 자신의 프로필 그림을 얻는다 하나, 내 친구의 그림 얻을 수있는 다른 :

// ----- Gets my own profile picture, using requestForMe ----- 
FBRequest *request = [FBRequest requestForMe]; 
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 
    //handle response 
    if(!error){ 
     //Some methods not included for breveity, includes facebookID used below 
     NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?type=large&return_ssl_resources=1", facebookID]]; 
     self.imageData = [[NSMutableData alloc] init]; 
     switcher = 1; 
     NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:pictureURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:2.0f]; 
     NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self]; 
     if (!urlConnection){ 
      NSLog(@"Failed to download picture"); 
     } 
    } 
}]; 
// ----- Gets a profile picture of my friend, using requestForMyFriends ----- 
FBRequest *requestForFriends = [FBRequest requestForMyFriends]; 
[requestForFriends startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 
    if(!error){ 
     //Other methods not included, including facebookFriendID 
     NSURL *friendPictureURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?type=large&return_ssl_resources=1", facebookFriendID]]; 
     self.supportImageData = [[NSMutableData alloc] init]; 
     switcher = 2; 
     NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:friendPictureURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:2.0f]; 
     NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self]; 
     if (!urlConnection){ 
      NSLog(@"Failed to download picture"); 
     } 
    } 
}]; 

두 요청이 전화를 걸를 당신은에 NSURLConnectionDataDelegate 방법을 가진이 발생할 수 있습니다 모두 두 개의 비동기 프로세스를 가지고

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    // As chuncks of the image are received, we build our data file 

    if (switcher == 1) [self.imageData appendData:data]; 
    if (switcher == 2)[self.supportImageData appendData:data]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 

    //When the entire image is finished downloading 
    if (switcher == 1) { 
     UIImage *image = [UIImage imageWithData:self.imageData]; //puts the completed picture into the UI 
     self.titleImageView.image = image; 
     [self.titleImageView setClipsToBounds:YES]; 
    } 

    if (switcher == 2) { 
     UIImage *supportImage = [UIImage imageWithData:self.supportImageData]; 
     self.supportImageView.image = supportImage; 
     [self.titleImageView setClipsToBounds:YES]; 
    } 
} 

답변

3

: NSURLConnectionDataDelegate 방법은, 내가 어떤 사진을로드 할 때 결정하는 switcher를 사용이 호출 중입니다. 그러나 동시에 발생하는 경우 서로 겹쳐서 이동합니다 (다운로드 할 데이터를 참조하기 위해 하나의 NSMutableData 변수를 사용하고있는 것 같습니다).

은 (AFNetworking처럼, 이상적인하는 NSOperation 기반의 접근 방식) 당신이 NSURLConnection 요청 각각에 대해 한 번 인스턴스화 할 수 있습니다 전용 클래스를 만들거나 대신 sendAsynchronousRequest를 사용 하나. 동시에 두 개의 동시 NSURLConnection 요청에 대해 단일 개체를 delegate으로 사용하지 마십시오. 당신은 미니멀 다운로드 작업을보고 싶어하면


, 그것과 같을 수 있습니다 당신이 그것을 사용하고자 할 때 다음

// NetworkOperation.h 

#import <Foundation/Foundation.h> 

typedef void(^DownloadCompletion)(NSData *data, NSError *error); 

@interface NetworkOperation : NSOperation 

- (id)initWithURL:(NSURL *)url completion:(DownloadCompletion)completionBlock; 

@property (nonatomic, copy) NSURL *url; 
@property (nonatomic, copy) DownloadCompletion downloadCompletionBlock; 

@end 

// NetworkOperation.m 

#import "NetworkOperation.h" 

@interface NetworkOperation() <NSURLConnectionDataDelegate> 

@property (nonatomic, readwrite, getter = isExecuting) BOOL executing; 
@property (nonatomic, readwrite, getter = isFinished) BOOL finished; 
@property (nonatomic, strong) NSMutableData *data; 

@end 

@implementation NetworkOperation 

@synthesize finished = _finished; 
@synthesize executing = _executing; 

- (id)initWithURL:(NSURL *)url completion:(DownloadCompletion)downloadCompletionBlock 
{ 
    self = [super init]; 
    if (self) { 
     self.url = url; 
     self.downloadCompletionBlock = downloadCompletionBlock; 

     _executing = NO; 
     _finished = NO; 
    } 
    return self; 
} 

#pragma mark - NSOperation related stuff 

- (void)start 
{ 
    if ([self isCancelled]) { 
     self.finished = YES; 
     return; 
    } 

    self.executing = YES; 

    NSURLRequest *request = [NSURLRequest requestWithURL:self.url]; 
    NSAssert(request, @"%s: requestWithURL failed for URL '%@'", __FUNCTION__, [self.url absoluteString]); 
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; 
    [connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 
    [connection start]; 
} 

- (void)setExecuting:(BOOL)executing 
{ 
    [self willChangeValueForKey:@"isExecuting"]; 
    _executing = executing; 
    [self didChangeValueForKey:@"isExecuting"]; 
} 

- (void)setFinished:(BOOL)finished 
{ 
    [self willChangeValueForKey:@"isFinished"]; 
    _finished = finished; 
    [self didChangeValueForKey:@"isFinished"]; 
} 

- (BOOL)isConcurrent 
{ 
    return YES; 
} 

#pragma mark NSURLConnectionDataDelegate methods 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    self.data = [NSMutableData data]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    if ([self isCancelled]) { 
     [connection cancel]; 
     self.executing = NO; 
     self.finished = YES; 
     return; 
    } 

    [self.data appendData:data]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    if (self.downloadCompletionBlock) { 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      self.downloadCompletionBlock(self.data, nil); 
      self.downloadCompletionBlock = nil; 
     }]; 
    } 

    self.executing = NO; 
    self.finished = YES; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    if (self.downloadCompletionBlock) { 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      self.downloadCompletionBlock(nil, error); 
      self.downloadCompletionBlock = nil; 
     }]; 
    } 

    self.executing = NO; 
    self.finished = YES; 
} 

@end 

그리고, 그것은 보일 수 있습니다 like :

NSOperationQueue *networkQueue = [[NSOperationQueue alloc] init]; 
queue.maxConcurrentOperationCount = 4; 

// ----- Gets my own profile picture, using requestForMe ----- 
FBRequest *request = [FBRequest requestForMe]; 
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 
    //handle response 
    if(!error) { 
     //Some methods not included for breveity, includes facebookID used below 
     NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?type=large&return_ssl_resources=1", facebookID]]; 

     [networkQueue addOperation:[[NetworkOperation alloc] requestWithURL:pictureURL completion:^(NSData *data, NSError *error) { 
      if (!error) { 
       self.meImageView.image = [UIImage imageWithData:data]; 
      } 
     }]]; 
    } 
}]; 
// ----- Gets a profile picture of my friend, using requestForMyFriends ----- 
FBRequest *requestForFriends = [FBRequest requestForMyFriends]; 
[requestForFriends startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 
    if(!error){ 
     //Other methods not included, including facebookFriendID 
     NSURL *friendPictureURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?type=large&return_ssl_resources=1", facebookFriendID]]; 

     [networkQueue addOperation:[[NetworkOperation alloc] requestWithURL:friendPictureURL completion:^(NSData *data, NSError *error) { 
      if (!error) { 
       self.friendImageView.image = [UIImage imageWithData:data]; 
      } 
     }]]; 
    } 
}]; 
+0

감사합니다. 각 요청에 대해 한 번 인스턴스화하는 전용 클래스에 대해 언급 할 때 더 자세히 설명해 줄 수 있습니까 (또는 작성 업 또는 가이드에 대해 알고 있다면 더 자세히 볼 수 있습니다). – daspianist

+1

@ daspianist 만약 당신이 "NSURLConnection NSOperationQueue"구글 (NSURLConnection NSOperationQueue) 당신은 링크를 참조하십시오 (단 하나의 확정적인 하나는 내가 당신을 추천). [AFNetworking] (https://github.com/AFNetworking/AFNetworking)을 사용하는 것이 좋습니다. 저는 (운영 기반 솔루션 (https://github.com/robertmryan/download-operation) 및 비 운영 기반 솔루션 (https://github.com/)을 포함하여) 몇 가지 예를 함께 보았습니다. robertmryan/download-manager)).하지만 직접 작성하기 전에 [AFNetworking] (https://github.com/AFNetworking/AFNetworking)을 사용하는 것이 좋습니다. – Rob

+0

감사합니다. Rob - AFNetworking 권장 사항과 함께 갈 것입니다! – daspianist

관련 문제