1

UIImageView我的故事板目前有两个,其中一个下载我自己的 Facebook 头像,另一个下载朋友的头像。

故事板布局

但是,我的问题是,只有 60% 的时间可以按预期工作,而其他 40% 的时间我自己的个人资料图片出现在我朋友的图片应该显示在底部的位置,而顶部的框仍然是空的。我不确定这是否是我在NSURLConnectionDataDelegate下载或完成视图时调用方法的结果,还是我调用 Facebook 的请求的性质。

我已将我的两个请求的精简版粘贴到 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方法,我使用switcher来决定何时加载哪张图片:

- (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];
    }
}
4

1 回答 1

3

您有两个异步过程,这两个过程都可能导致您的 NSURLConnectionDataDelegate方法self被调用。但是,如果它们同时发生,它们将相互叠加(您可能正在使用单个NSMutableData变量来引用正在下载的数据)。

要么创建专用类,您可以为两个NSURLConnection请求中的每一个实例化一次(NSOperation基于方法,如AFNetworking是理想的),或者sendAsynchronousRequest改用它。但是不要同时使用一个对象作为delegate两个并发NSURLConnection请求的对象。


如果你想看一个极简的下载操作,它可能看起来像:

//  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

然后,当你想使用它时,它可能看起来像:

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];
            }
        }]];
    }
}];
于 2013-08-11T16:09:48.123 回答