调用NSURLConnectionDataDelegate方法下载图像只能偶尔(Calls to N

2019-10-18 11:47发布

我目前有两个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];
    }
}

Answer 1:

你有两个异步进程,这两者都会导致有你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];
            }
        }]];
    }
}];


文章来源: Calls to NSURLConnectionDataDelegate methods to download images only works occasionally