NSURLConnection未在主线程上运行

时间:2014-12-23 08:09:58

标签: ios objective-c multithreading nsurlconnection nsoperation

我看了NSURLConnection doesn't call delegate methodsNSURLConnection didReceiveData not called等等,但我无法找到解决问题的方法。我已经验证我的URL有效,并且我能够使用常规nsurlconnection但不使用委托方法接收数据。

我已经设置了导入操作,但我的委托方法没有被调用。经过一些调试和研究后,我意识到nsurlconnection没有在主线程上运行,我相信这就是为什么我的委托方法没有被调用。我不知道还有什么可以尝试的。我很感激帮助。

我的导入类

#import "importOperation.h"

@interface importOperation ()<NSURLConnectionDelegate>
@property (nonatomic, strong) NSURL* url;
@property (nonatomic, strong) NSURLConnection* connection;
@property (nonatomic, strong) NSMutableData* buffer;
@property (nonatomic) long long int expectedContentLength;
@property (nonatomic, readwrite) NSError* error;
@property (nonatomic) BOOL isExecuting;
@property (nonatomic) BOOL isConcurrent;
@property (nonatomic) BOOL isFinished;
@end
@implementation importOperation
-(id)initWithURL:(NSURL *)url
{
    self = [super init];
    if (self) {
        self.url = url;
    }
    return self;
}
-(void)start
{
    NSURLRequest * request = [NSURLRequest requestWithURL:self.url];
    self.isExecuting = YES;
    self.isConcurrent = YES;
    self.isFinished = NO;

    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
    self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
}];

}
#pragma mark NSURLConnectionDelegate
-(NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response
{
    return request;
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    self.expectedContentLength = response.expectedContentLength;
    self.buffer = [NSMutableData data];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.buffer appendData:data];
    self.progressCallback(self.buffer.length / (float)self.expectedContentLength);
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {// implemented}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    self.data = self.buffer;
    self.buffer = nil;
    self.isExecuting = NO;
    self.isFinished = YES;
}
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{// implemented}
- (void)setIsExecuting:(BOOL)isExecuting
{// implemented}
- (void)setIsFinished:(BOOL)isFinished
{// implemented}
- (void)cancel
{// implemented}
@end

这就是我调用导入操作的方式

-(void)getStuff:(void(^) (NSArray *result, NSError *error))completion
{

    __block importOperation *anImportOperation = nil;
    void(^completionBlock)(void)= ^(void){
        NSData * importOperationData = [anImportOperation data];
        NSError * error;
        NSDictionary * jsonDictionary = [NSJSONSerialization JSONObjectWithData:importOperationData options:NSJSONReadingMutableContainers error:&error];
        NSLog(@"parse data %@",jsonDictionary);

        completion([jsonDictionary objectForKey:@"data"],error);
    };
    anImportOperation =[[importOperation alloc]initWithURL:[ServiceManager baseURLWithResource:@"beers"]];
    [anImportOperation setCompletionBlock:completionBlock];
    [self.operationQueue addOperation:anImportOperation];

    if ([NSThread isMainThread] ==YES) {
        completionBlock();
    }
    else{
        dispatch_sync(dispatch_get_main_queue(),completionBlock);
    }

这是日志声明

2014-12-22 23:42:58.430 Cheers[4736:621077] requested string https://api.brewerydb.com/v2/beers?key=APIKE
2014-12-22 23:42:58.456 Cheers[4736:621076] Is NOT main thread
2014-12-22 23:42:58.520 Cheers[4736:621136] PATH TO SQL STORE /Users/bla/Library/Developer/CoreSimulator/Devices/817B8B49-6316-40BD-ABF1-98C34FFD9299/data/Containers/Data/Application/252FA241-CE21-4C0E-A4DB-32D3DECC9DFB/Documents/CheersDataModel.sqlite
2014-12-22 23:42:58.647 Cheers[4736:620751] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'data parameter is nil'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010dc72f35 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010d90bbb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010dc72e6d +[NSException raise:format:] + 205
    3   Foundation                          0x000000010d5b01bf +[NSJSONSerialization JSONObjectWithData:options:error:] + 67
    4   Cheers                          0x000000010d006396 __27-[ServiceManager getBeers:]_block_invoke + 118
    5   libdispatch.dylib                   0x00000001105107f4 _dispatch_client_callout + 8
    6   libdispatch.dylib                   0x00000001104fbec9 _dispatch_barrier_sync_f_slow_invoke + 275
    7   libdispatch.dylib                   0x00000001105107f4 _dispatch_client_callout + 8
    8   libdispatch.dylib                   0x00000001104f98fb _dispatch_main_queue_callback_4CF + 949
    9   CoreFoundation                      0x000000010dbdafe9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    10  CoreFoundation                      0x000000010db9deeb __CFRunLoopRun + 2043
    11  CoreFoundation                      0x000000010db9d486 CFRunLoopRunSpecific + 470
    12  GraphicsServices                    0x00000001121739f0 GSEventRunModal + 161
    13  UIKit                               0x000000010e2a2420 UIApplicationMain + 1282
    14  Cheers                              0x000000010d009153 main + 115
    15  libdyld.dylib                       0x0000000110545145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

2 个答案:

答案 0 :(得分:2)

您的importOperationDatanil,这就是它崩溃的原因。您需要验证从服务器返回的值。

NSData * importOperationData = [anImportOperation data];
        NSError * error;

if(importOperationData)
{
   NSDictionary * jsonDictionary = [NSJSONSerialization JSONObjectWithData:importOperationData options:NSJSONReadingMutableContainers error:&error];
   if(jsonDictionary)
   {
       completion([jsonDictionary objectForKey:@"data"],error);
   }
}

答案 1 :(得分:0)

您正在从非主线程开始请求,因为您正在继承NSOperation并将其添加到某些self.operationQueue,这可能主队列。< / p>

但问题是,在将操作添加到队列后调用完成块。删除此代码:

if ([NSThread isMainThread] ==YES) {
    completionBlock();
}
else{
    dispatch_sync(dispatch_get_main_queue(),completionBlock);
}