1

Я вхожу в приложение iOS7, это своего рода приложение для социальной сети с сообщениями с изображениями и бэкэнд, которые сохраняют все данные, отправленные клиентом. Клиент iOS отправляет информацию о сообщении через json и после отправки информации начинает отправлять изображение через многостраничную форму, используя AFNetworking.Ожидание отправки многостраничного изображения завершено

Мне нужно уведомить, когда изображение будет отправлено, так что я могу обновить основной вид приложения с новыми сообщениями, включая недавно опубликованные клиентом. В практике, если я запрашиваю бэкэнд для последних сообщений, а multipart еще не закончен, отправка изображения прерывается и не удается отправить изображение.

Бэкэнд разрабатывается в WCF и является веб-сервисом RESTful JSON.

Вот метод, который отправляет сообщение в бэкэндом:

+(void)addPostToServerAddtext:(NSString *)text addimage:(UIImage *)image addbeach:(NSString *)beach location:(NSString*)location; 
{ 
    NSLog(@"entro a addPost"); 
    NSString *urlBackend = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"URLBackend"]; 

    NSData* dataImage = UIImageJPEGRepresentation(image, 1.0); 
    NSString* ImageName = [NSString stringWithFormat:@"%@_%@.jpg",idUser ,dateToServer]; 
    NSString *jsonRequest = [NSString stringWithFormat:@"{\"Date\":\"%@\"...."]; 

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@newPost",urlBackend]]; 

    NSMutableURLRequest *request = [ [NSMutableURLRequest alloc] initWithURL:url]; 
    NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]]; 

    [request setHTTPMethod:@"POST"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
    [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"]; 
    [request setHTTPBody:requestData]; 

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
    [connection start]; 

    if (image != nil) { 

     AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
     [manager POST:[NSString stringWithFormat:@"%@FileUpload",urlBackend] 
      parameters:nil 
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { 
      [formData appendPartWithFileData:dataImage name:@"image" fileName:ImageName mimeType:@"image/jpg" ]; 
     } 
       success:^(AFHTTPRequestOperation *operation, id responseObject) { 
      NSLog(@"Success: %@", responseObject); 
     } 
       failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
      NSLog(@"Error: %@", error); 
     }]; 
    } 
} 
+0

И использование блока успеха не работает? – Wain

+0

Хорошая точка, но этот метод находится в модели моего MVC architechture, и я хочу быть замеченным в контроллере главной страницы ... – jandresrodriguez

+0

@Wain Я думаю, что проблема в том, что у него есть [другой вопрос] (http: //stackoverflow.com/questions/20072609/update-property-using-geocoder-to-get-user-actual-address-exc-bad-access), в котором он выдает запрос, и неясно, как подождать он (и пробовал только ждать пять секунд). Я думаю, он ищет указания о том, как получить метод, который вызывает «addPostToServerAddtext», когда запрос завершен. – Rob

ответ

1

Пара мыслей:

  1. Вы говорите:

    клиент IOS посылает информацию о сообщении через json и после отправки информации, он начинает отправлять изображение через многостраничную форму с использованием AFNetworking.

    Технически вы не ждете, пока информация будет отправлена, но вы делаете это одновременно. Вы хотите, чтобы они были параллельными? Или последовательный? Или почему не только один запрос, который помещает информацию, а также изображение?

  2. Я бы предложил использовать AFNetworking для обоих запросов. У вас есть мощная инфраструктура для управления сетевыми запросами, и вам неловко видеть волосатый код NSURLConnection.

    Если вы держите NSURLConnection код там, обратите внимание, что вы делаете не хотите startNSURLConnection, если вы не использовали initWithRequest:delegate:startImmediately: с NO для этого последнего параметра. Вы эффективно запускаете его дважды, что может вызвать проблемы. Я предлагаю удалить звонок start.

  3. Установка все это в сторону, что вы хотите сделать, это добавить параметр завершения блока в ваш метод, например, что-то вроде:

    + (void)addPostToServerAddtext:(NSString *)text addimage:(UIImage *)image addbeach:(NSString *)beach location:(NSString*)location completion:(void (^)(id responseObject, NSError *error))completion 
    { 
        // ... 
    
        if (image != nil) { 
    
         AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
         [manager POST:[NSString stringWithFormat:@"%@FileUpload",urlBackend] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { 
          [formData appendPartWithFileData:dataImage name:@"image" fileName:ImageName mimeType:@"image/jpg" ]; 
         } success:^(AFHTTPRequestOperation *operation, id responseObject) { 
          if (completion) completion(responseObject, nil); 
         } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
          if (completion) completion(nil, error); 
         }]; 
    
        } 
    } 
    

    Вы бы затем вызвать, что вот так:

    [Persistence addPostToServerAddtext:text addimage:image addbeach:nil location:annotation completion:^(id responseObject, NSError *error) { 
        if (error) { 
         // handle error 
         return 
        } 
    
        // otherwise use the responseObject 
    }]; 
    

    Теперь, я не знаю, какие параметры вы хотите вернуться в вашем блоке завершения (я предполагаю, что вы хотите, чтобы вернуть то, что AFHTTPRequestOperationManager сделал), а просто изменить параметры для этого блока completion как соответствует вашим потребностям ,

  4. Unrelated к первоначальному вопросу, но я заметил, что вы строите jsonRequest так:

    NSString *jsonRequest = [NSString stringWithFormat:@"{\"Date\":\"%@\"...."]; 
    

    Это немного рискованно, если какие-либо из этих полей включает определённый пользователь информацию (например, что если пользователь используется двойные кавычки в предоставленной информации).Я предлагаю вам создать словарь, а затем построить из него jsonRequest. Он будет более надежным. Таким образом:

    NSDictionary *dictionary = @{@"Date" : date, 
              @"Message" : message}; 
    NSError *error = nil; 
    NSData *request = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error]; 
    if (error) 
        NSLog(@"%s: dataWithJSONObject error: %@", __FUNCTION__, error); 
    

    Или, если вы используете AFNetworking, я считаю, что будет делать это преобразование JSON вашего словаря для вас. Но, в заключение, будьте очень осторожны в создании строк JSON самостоятельно, по крайней мере, если запрос может содержать любую предоставленную пользователем информацию.

+0

Вы имеете в виду, что я могу отправить json и изображение в одном запросе, используя AFNetworking? это будет потрясающе! Во-вторых, многопоточная форма AFNewtorking работает в фоновом потоке, я могу заставить addPostToServer также работать в фоновом режиме? – jandresrodriguez

+0

@JuanAndresRodriguez Вы можете взять 'NSDictionary', который я предложил вам создать в моей точке №4, и просто передать это как значение' parameters' метода AFNetworking 'POST'. Очевидно, вам придется изменить код сервера, чтобы обрабатывать как параметры '$ _POST', так и загружаемую загрузку' $ _FILES', но это не так сложно. Но это гораздо более логичный способ продолжения. Чтобы иметь два одновременных запроса и выяснить, как определить успех (например, что делать, если один удастся, а другой - нет), может стать уродливым. – Rob

+0

@JuanAndresRodriguez Относительно вашего запроса на создание 'addPostToServerAddtext' запускается асинхронно, поскольку AFNetworking выполняет асинхронный запрос,' addPostToServerAddtext' уже ведет себя асинхронно (эффективно): вот почему нам пришлось добавить параметр «завершить», потому что он уже ведет асинхронную работу , благодаря AFNetworking. – Rob

Смежные вопросы