2013-06-04 2 views
4

enter image description hereAFNetworking하고있는 NSURLConnection

편집 : 나는 그것을 호출하지있을 때 AFNetworking이며, [NSThread main]에서 실행 NSURLConnection 이유 스크린 샷에서 강조 표시된 행은, 내가 문제가있는 것입니다.

내 프로젝트에 AFNetworking을 사용하고 있지만 Instrument에서 Time Profiler를 실행할 때 NSURLConnection에 대한 주 스레드에서 많은 활동을보고 있는데, 나는 이것이 내가 원하는 것이 아님을 느낍니다.

내 방법은

- (void)parseArticles { 
    NSMutableArray *itemsToParse = [[FMDBDataAccess sharedDatabase] getItemsToParse]; 

    NSMutableArray *operations = [[NSMutableArray alloc] init]; 


    for (Post *p in itemsToParse) { 

     NSMutableString *strURL = [NSMutableString new]; 
     [strURL appendString:@"http://xxxxxxxxxxxxxxxxxxxxxx.php?url="]; 
     [strURL appendString:[p href]]; 

     NSURL *url = [NSURL URLWithString:strURL]; 
     NSURLRequest *request = [NSURLRequest requestWithURL:url]; 

     AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 
     [[ParserClient sharedInstance] registerHTTPOperationClass:[AFHTTPRequestOperation class]]; 

     [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 

      dispatch_async(loginParseQueue, ^{ 

       Parser *parse = [[Parser alloc] init]; 
       [parse parseLink:responseObject rowID:[p rowID]]; 
      }); 
     } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
      NSLog(@"%@",error); 
     }]; 
     [operations addObject:operation]; 
    } 
    NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 
    [operationQueue setMaxConcurrentOperationCount:3]; 
    [operationQueue addOperations:operations waitUntilFinished:NO]; 
} 

왜 메인 스레드를 사용하여 AFNetworking 것입니까? 어떻게 수정해야합니까?

답변

4

AFNetworking는 메인 스레드가 아닌 자식 스레드에서 실행되고 있지만, 모든 스레드는 당신이 게시 이미지에있는 주요 방법이있다. 이건 주 스레드가 아니에요. 이제 말해봐. 무엇을 고치고 싶니?

+0

그것은 내가 [NSURLConnection (loader)] 등 [NSThread main]이라고 표시된 화살표 아래에 관심이있는 인스트루먼트 스크린 샷의 강조된 부분입니다. 메인 스레드가 아닌가요? – Nick

+0

고마워, 내가 혼란스러워하고 기본 스레드라고 가정했다고 생각해. – Nick

-2

편집 :

다음은 백그라운드 스레드에서 작업을 실행하는 데 필요한 코드입니다. UI 스레드에서 호출 된 모든 함수의 사용은 UI 스레드에서 실행됩니다. 아래에 지정된 것과 유사한 기술을 사용하여 백그라운드 스레드에서 작업을 실행 한 다음 결과를 나중에 사용할 수 있도록 UI 스레드에 다시 전달할 수 있습니다.

는 특수한 유형 (블록)을 지정합니다 그래서 당신은 주위에 코드 블록을 전달할 수 있습니다 여기에

당신은 당신의 AFHTTPRequestOperation 내 sendSynchronousRequest 전화를 대체 할 수있다, 내가 사용하는 기술입니다.

typedef void (^NetworkingBlock)(NSString* stringOut); 

그런 다음 UI 스레드를 고정시키지 않도록 백그라운드 스레드로 디스패치해야합니다.

- (void) sendString:(NSString*)stringIn url:(NSString*)url method:(NSString*)method completion:(NetworkingBlock)completion { 
    //build up a request. 
    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; 
    NSData *postData = [stringIn dataUsingEncoding:NSUTF8StringEncoding]; 
    [request setHTTPMethod:method]; 
    [request setValue:[NSString stringWithFormat:@"%d", postData.length] forHTTPHeaderField:@"Content-Length"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; //or whatever 
    [request setHTTPBody:postData]; 

    //dispatch a block to a background thread using GCD (grand central dispatch) 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     NSURLResponse *response; 
     NSError* error; 

     //request is sent synchronously here, but doesn't block UI thread because it is dispatched to another thread. 
     NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

     //call complete, so now handle the completion block. 
     if (completion) { 
      //dispatch back to the UI thread again 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       if (responseData == nil) { 
        //no response data, so pass nil to the stringOut so you know there was an error. 
        completion(nil); 
       } else { 
        //response received, get the content. 
        NSString *content = [[NSString alloc] initWithBytes:[responseData bytes] length:responseData.length encoding:NSUTF8StringEncoding]; 
        NSLog(@"String received: %@", content); 

        //call your completion handler with the result of your call. 
        completion(content); 
       } 
      }); 
     } 
    }); 
} 

이처럼 사용하여 여기에

그것을 할 UI 스레드를 사용하지 않고 완료되면 블록을 호출 한 후 백그라운드 스레드에서 물건을 호출하고 응답을 기다린하는 함수입니다 :

- (void) myFunction { 
    [self sendString:@"some text in the body" url:@"http://website.com" method:@"POST" completion:^(NSString *stringOut) { 
     //stringOut is the text i got back 
    }]; 
} 
+0

당신은 질문에 대답하지 않습니다 : AFNetworking이 메인 스레드를 사용하는 이유는 무엇입니까? 어떻게 수정해야합니까? – samir

+0

나는 내 게시물 뒤에있는 의도를 설명하기 위해 편집을했다. 희망이 도움이! –

+0

감사합니다, 다른 스레드에서 일을 실행하는 방법을 알고, 난 그냥 NSURLConnection 호출하는 AFNetworking 사용하면 이해할 수없는 주 스레드에 있습니다. – Nick

4

AFNetworking이 경로에 완료 블록 "successCallbackQueue"를 사용하기 때문이다 :

AFHTTPRequestOperation.m :

dispatch_queue_t backgroundQueue = dispatch_queue_create("com.name.bgqueue", NULL); 
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 
operation.successCallbackQueue = backgroundQueue; 
operation.failureCallbackQueue = backgroundQueue; 
:

self.completionBlock = ^{ 
    if (self.error) { 
     if (failure) { 
      dispatch_async(self.failureCallbackQueue ?: dispatch_get_main_queue(), ^{ 
       failure(self, self.error); 
      }); 
     } 
    } else { 
     if (success) { 
      dispatch_async(self.successCallbackQueue ?: dispatch_get_main_queue(), ^{ 
       success(self, self.responseData); 
      }); 
     } 
    } 
}; 

당신은 단순히 성공과 실패 완료 블록에 다른 스레드를 할당 할 수 있습니다

+0

2.0 AFNetworking 이전에이 코드를 사용 중이며 충돌이 발생합니다. – CMVR