NSURLConnection и NSURLConnectionDelegate работают в другом потоке

как описано в заголовке, я сделал такой NSURLConnection. Но я обнаружил, что метод делегата не может быть запущен. Кто-нибудь знает, как с этим бороться?

редактировать: мой делегат работает в основном потоке, а NSURLConnection работает в очереди операций. Теперь дело в том, что: NSURLConnection работает нормально, но делегат не запускается.

изменить 2: я использовал метод класса [NSURLConnection connectionWithRequest: делегат:]

вот моя основная очередь

 NSOperationQueue *queuePhoto = [[NSOperationQueue alloc] init];
 NSInvocationOperation *invocationOperationPhotos = [[NSInvocationOperation alloc] initWithTarget:self   selector:@selector(transferToServerAddimages:) object:arrayOfASection]; 
//                        [invocationOperationPhotos addObserver:self forKeyPath:@"isExecuting" options:0 context:invocationOperationPhotos];
 //                        [invocationOperationPhotos addObserver:self forKeyPath:@"isCancelled" options:0 context:invocationOperationPhotos];
//                        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(<#selector#>) name:@"isExecuting" object:nil];
                        [invocationOperationPhotos setQueuePriority:NSOperationQueuePriorityHigh];
                    [queuePhoto addOperation:invocationOperationPhotos];
                    [mutableArrayPhotoQueue addObject:queuePhoto];
                    [invocationOperationPhotos release];
                    [queuePhoto release];

вот мой NSURLConnection:

- (void) transferToServerAddimages:(NSArray *) arrayToAdd
{
NSLog(@"[NSOperationQueue currentQueue]: %@", [NSOperationQueue currentQueue]);

NSString *murphoAppPrefix = [[AppDelegate sharedAppDelegate] murphoAppPrefix];
// setting up the request object now
NSString *urlString = [murphoAppPrefix stringByAppendingString:@"addPhotos.php"];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];

/*
 add some header info now
 we always need a boundary when we post a file
 also we need to set the content type
 */
// set header value ,   some random text that will never occur in the body
NSString *boundary = @"---------------------------14737809831466499882746641449";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];

/*
 now lets create the body of the post
 */
NSMutableData *body = [NSMutableData data];

//  email part    
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];    
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"email\"\r\n\r\n%@", self.trip.whoCreate.email] dataUsingEncoding:NSUTF8StringEncoding]];

//  password part
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];    
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"password\"\r\n\r\n%@", self.trip.whoCreate.psw] dataUsingEncoding:NSUTF8StringEncoding]];

//  image part
NSInteger subCount=0;
for (NSDictionary *aDict in arrayToAdd) {
    //  belonging part

    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];    
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"r_whichShortTrip%d\"\r\n\r\n%@", subCount, [aDict objectForKey:@"r_whichShortTrip"]] dataUsingEncoding:NSUTF8StringEncoding]];

    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];    
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"uniqueId%d\"\r\n\r\n%@", subCount, [aDict objectForKey:@"uniqueId"]] dataUsingEncoding:NSUTF8StringEncoding]];

    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];    
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"createdTime%d\"\r\n\r\n%@", subCount, [aDict objectForKey:@"createdTime"]] dataUsingEncoding:NSUTF8StringEncoding]];

    UIImage *imageFile = [aDict objectForKey:@"image"];
    NSData *imageData = UIImageJPEGRepresentation(imageFile, 1.0);
    NSString *imageName = [[URLConnect createUUID] stringByAppendingString:@".jpg"];
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];    
    [body appendData:[[NSString stringWithFormat: 
                       @"Content-Disposition: form-data; name=\"image%d\"; filename=%@\r\n", subCount, imageName]                          dataUsingEncoding:NSUTF8StringEncoding]];  
    [body appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[NSData dataWithData:imageData]];
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

    UIImage *thumbnail = [aDict objectForKey:@"thumbnail"];
    NSData *thumbnailData = [NSData dataWithData:UIImageJPEGRepresentation(thumbnail, 1)];
    NSString *thumbnailName = [[URLConnect createUUID] stringByAppendingString:@".jpg"];
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];    
    [body appendData:[[NSString stringWithFormat: 
                       @"Content-Disposition: form-data; name=\"thumbnail%d\"; filename=%@\r\n", subCount++, thumbnailName]                          dataUsingEncoding:NSUTF8StringEncoding]];  
    [body appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[NSData dataWithData:thumbnailData]];
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
}


[body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the reqeust
[request setHTTPBody:body];

// now lets make the connection to the web
[NSURLConnection connectionWithRequest:request delegate:self];

}

вот мой делегат:

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    [[[AppDelegate sharedAppDelegate] mArrayOfFailedConnection] addObject:connection];
     [connection cancel];
     connection = nil;
}


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"response: %@", response);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"connection: %@", connection);
}

person anna    schedule 03.07.2012    source источник
comment
Если в вашем потоке нет цикла выполнения, NSURLConnection не будет работать.   -  person Lily Ballard    schedule 03.07.2012
comment
вы добавили эту строку [соединение startConnection];   -  person MobileApp Developer    schedule 03.07.2012
comment
@Kevin Ballard, только что отредактированный, делегат находится в основном потоке и не будет работать, а не NSURLConnection.   -  person anna    schedule 03.07.2012
comment
@Arundhati, я использовал метод класса [NSURLConnection connectionWithRequest: delegate:].   -  person anna    schedule 03.07.2012
comment
@ Анна, вы должны запустить соединение в потоке с циклом выполнения. Затем в этом потоке будут вызываться методы делегата. Сам ввод-вывод соединения всегда происходит в другом потоке, управляемом Foundation.   -  person Jason Coco    schedule 03.07.2012
comment
@Jason Coco: я не думаю, что start нужен. Показано ниже (из [developer.apple.com/library/ios/#documentation/Cocoa/Reference/ - (void)start Обсуждение Вызов этого метода необходим, только если вы создаете соединение с методом initWithRequest:delegate:startImmediately: и предоставляете НЕТ для параметра startImmediately. Если вы не планируете подключение в цикле выполнения или очереди операций перед вызовом этого метода, подключение планируется в текущем цикле выполнения в режиме по умолчанию.**   -  person anna    schedule 03.07.2012
comment
Start не нужен, но он неявно вызывается этими другими методами. Ваше соединение запускается в потоке, в котором не установлен цикл выполнения (независимо от того, в какой поток отправляется операция), и поэтому вы никогда не получите делегированные обратные вызовы. Отправьте свою операцию в основную очередь: [[NSOperationQueue mainQueue] addOperation:myAsyncNetworkOperation]   -  person Jason Coco    schedule 03.07.2012
comment
@Mehul, я вставил свой код. пожалуйста, проверьте   -  person anna    schedule 03.07.2012
comment
@JasonCoco, я вставил свой код, проверьте, пожалуйста. Кстати, я пытаюсь добавить start.   -  person anna    schedule 03.07.2012
comment
@JasonCoco, я попробовал код: [[NSURLConnection connectionWithRequest: запрос делегата: сам] start]; но делегат все равно не запустится.   -  person anna    schedule 03.07.2012
comment
@anna ваша очередь операций queuePhoto отправляется в фоновый поток без установленного цикла выполнения. Это ваша проблема. Добавьте операцию в mainQueue, возвращенную NSOperationQueue.   -  person Jason Coco    schedule 03.07.2012
comment
@JasonCoco, mainQueue: возвращает очередь операций, связанную с основным потоком. Если я отправлю свою операцию в mainQueue, я боюсь, что это заблокирует приложение или, по крайней мере, снизит скорость. Итак, есть ли другой способ?   -  person anna    schedule 03.07.2012
comment
Ну, вы сказали, что вам все равно нужны обратные вызовы делегатов в основном потоке, так что вы это получили. Фактический сетевой ввод-вывод выполняется в частном потоке и не блокирует основной поток. Просто убедитесь, что возвращаетесь из методов делегата как можно быстрее.   -  person Jason Coco    schedule 03.07.2012


Ответы (2)


На самом деле, когда вы устанавливаете селектор для операции как «transferToServerAddimages», это означает, что когда эта функция будет выполнена полностью, ваша операция будет завершена, также поскольку NSUrlConnection вызывает своих делегатов в том же потоке, в котором он был запущен, поэтому, вероятно, этот поток (OperationQueue) было завершено до того, как пришел ответ. Если вы действительно хотите использовать NSOperationQueue, то лучше использовать функцию «sendAsynchronousRequest:queue:completionHandler:» из NSUrlConnection.

person abhay    schedule 23.10.2012

Что делегат, NSOperation? Возможно, ваша операция вызывает -[connectionWithRequest:delegate:] и завершает работу, что приводит к ее завершению и удалению. Поместите NSLog в сделку операции, чтобы увидеть, работает ли она.

Предполагая, что вся операция — это NSURLConnection транзакции, вам не нужно оборачивать транзакцию в NSOperation для обеспечения параллелизма, поскольку эти транзакции уже являются асинхронными. Но если вы действительно хотите использовать NSOperation (в целях координации и т. д.), сделайте его «параллельным» и поместите в основную очередь. Те виды сложнее, но есть примеры.

person Pierre Houston    schedule 22.06.2013