2014-01-03 3 views
1

В конечном итоге я пытаюсь преобразовать массив фотографий, которые находятся в словаре в форме url rep, в base64 для отправки по json.Перейдите из изображения url rep из библиотеки ресурсов в base64

Вот код словаря и журнал его:

NSDictionary *dict = [self.form dictionaryWithValuesForKeys:keys]; 
    NSLog(@"dict::%@",dict); 

NSLog:

dict::{ 
    boardLodgingFurnished = "<null>"; 
    caption = "<null>"; 
    cars = ""; 
    photos =  (
       { 
      caption = ""; 
      urlRep = "assets-library://asset/asset.JPG?id=CE8A426B-3B59-4172-8761-CC477F3BB3EE&ext=JPG"; 
     }, 
       { 
      caption = ""; 
      urlRep = "assets-library://asset/asset.JPG?id=F4B68A42-1CA0-4880-9FB5-177CB091A28C&ext=JPG"; 
     } 
    ); 
    yearsAtLocation = ""; 
    yearsInTheBusiness = ""; 
} 

Так что для каждой фотографии в словаре Я хотел бы взять urlRep и преобразовать его в base64 string и замените urlRep на него в словаре.

Я имею право now..not уверен, если я иду в правильном направлении:

for (id imageURL in [dict objectForKey:@"photos"]) 
{ 
ALAssetsLibrary *library = [ALAssetsLibrary new]; 
      ALAsset *ourAsset = [self assetForURL:imageURL withLibrary:library]; 

      /* Check out ALAssets */ 
      NSLog(@"%@", ourAsset); 

      ALAssetRepresentation *representation = [ourAsset defaultRepresentation]; 
      CGImageRef imageRef = [representation fullResolutionImage]; 

      //TODO: Deal with JPG or PNG 
      NSData *imageData = UIImageJPEGRepresentation([UIImage imageWithCGImage:imageRef], 0.1); 
     NSLog(@"imagedata??%@",  [imageData base64EncodedString]); 
//need to know how to add this back to dict 
} 

ниже метод вызывается из выше, но падает на время цикла с

-[__NSDictionaryI scheme]: unrecognized selector sent to instance 0x166dd090 
2014-01-03 10:57:27.361 Inspection App[2728:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI scheme]: unrecognized selector sent to instance 0x166dd090' 

метод

- (ALAsset *)assetForURL:(NSURL *)url withLibrary:(ALAssetsLibrary *)assetsLibrary { 
    __block ALAsset *result = nil; 
    __block NSError *assetError = nil; 
    dispatch_semaphore_t sema = dispatch_semaphore_create(0); 

    [assetsLibrary assetForURL:url resultBlock:^(ALAsset *asset) { 
     result = asset; 
     dispatch_semaphore_signal(sema); 
    } failureBlock:^(NSError *error) { 
     assetError = error; 
     dispatch_semaphore_signal(sema); 
    }]; 


    if ([NSThread isMainThread]) { 
     while (!result && !assetError) { 
      [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
     } 
    } 
    else { 
     dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
    } 

    return result; 
} 

редактировать:

if (photoUrls.count) { 
      for (id photos in photoUrls){ 
      NSString *urlString = photos; 
      [self base64ImageAtUrlString:urlString result:^(NSString *base64) { 

       NSLog(@"imagedata??%@", base64); 
      }]; 
     } 
     } 
     else { 
      NSLog(@"where are my urls?"); 
     } 

     NSMutableDictionary *jsonWithPhotos = [dict mutableCopy]; 

     [jsonWithPhotos setObject:convertedImages forKey:@"photo64"]; 
     NSLog(@"jjson photos::%@", jsonWithPhotos); 

обновленного метод

- (void)base64ImageAtUrlString:(NSString *)urlString result:(void (^)(NSString *))completion { 
    NSURL *url = [NSURL URLWithString:urlString]; 
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 

    [library assetForURL:url resultBlock:^(ALAsset *asset) { 

     // borrowing your code, here... didn't check it.... 
     ALAssetRepresentation *representation = [asset defaultRepresentation]; 
     CGImageRef imageRef = [representation fullResolutionImage]; 

     //TODO: Deal with JPG or PNG 
     NSData *imageData = UIImageJPEGRepresentation([UIImage imageWithCGImage:imageRef], 0.1); 
     NSString *base64 = [imageData base64EncodedString]; 
     completion(base64); 
     [convertedImages addObject:base64]; 

//  NSLog(@"converted::%@",convertedImages); 

    } failureBlock:^(NSError *error) { 
     NSLog(@"that didn't work %@", error); 
    }]; 
} 

Когда я войти jsonWithPhotos объект photo64 просто пустой массив

+0

Вы действительно поняли, что данные изображения могут быть «большими» и что для его кодирования в base64 потребуется буфер данных, который на 25% больше изображения. И это умноженное на количество изображений, безусловно, вызовет давление в памяти и в конечном итоге приведет к сбою. – CouchDeveloper

+0

, так как вы предлагаете отправлять изображения на сервер? – BluGeni

+0

Если вы хотите «обрабатывать» изображения (скажем, кодировку base64), я бы рекомендовал, чтобы в памяти в настоящее время хранилось только ограниченное количество изображений, возможно, только * one *. Вы можете выполнить это с помощью очереди (очереди отправки или NSOperationQueue), которая одновременно выполняет определенное количество задач. Вы можете даже поставить в очередь все задачи сразу, если вы ссылаетесь только на изображение с URL-адресом. При отправке данных на сервер вы можете создать резервную копию данных в файле и использовать NSInputStream и инициализировать запрос через свойство HTTPBodyStream. – CouchDeveloper

ответ

2

Катастрофой является из-за ложное предположение в коде о словаре. Учитывая посланное описание словаря разобранного в формате JSON, вы должны были бы получить URLs так:

// collect the photo urls in an array 
NSMutableArray *photoUrls = [NSMutableArray array]; 

// photos is an array of dictionaries in the dictionary 
NSArray *photos = dict[@"photos"]; 
for (NSDictionary *photo in photos) { 
    // photo is a dictionary containing a "caption" and a "urlRep" 
    [photoUrls addObject:photo[@"urlRep"]]; 
} 

Теперь вы можете приступить к методу, работа которого только преобразование. Ваш вопрос может содержать гораздо больше вопросов о том, как это сделать. Я рекомендую начинать просто. Посмотрите, можете ли вы сделать одно преобразование. Проверьте это, написав обратное, от base64 до изображения.

Edit 0: Без глубоко проверить это, я бы перестроить вашу кодировку попытку выглядеть следующим образом:

- (void)base64ImageAtUrlString:(NSString *)urlString result:(void (^)(NSString *))completion { 
    NSURL *url = [NSURL URLWithString:urlString]; 
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 

    [library assetForURL:url resultBlock:^(ALAsset *asset) { 

     // borrowing your code, here... didn't check it.... 
     ALAssetRepresentation *representation = [asset defaultRepresentation]; 
     CGImageRef imageRef = [representation fullResolutionImage]; 

     //TODO: Deal with JPG or PNG 
     NSData *imageData = UIImageJPEGRepresentation([UIImage imageWithCGImage:imageRef], 0.1); 
     NSString *base64 = [imageData base64EncodedString]; 
     completion(base64); 

    } failureBlock:^(NSError *error) { 
     NSLog(@"that didn't work %@", error); 
    }]; 
} 

Назовите это так:

if (photoUrls.count) { 
    NSString *urlString = photoUrls[0]; 
    [self base64ImageAtUrlString:urlString result:^(NSString *base64) { 
     NSLog(@"imagedata??%@", base64); 
    }]; 
} else { 
    NSLog(@"where are my urls?"); 
} 

После того, как он работает, см если вы можете изменить его, сделав изображение из данных base64. Наконец, как только все это работает, вы можете справиться с потенциальными проблемами памяти. Мой совет - рассматривать кодировку по одному, отправлять по одному на сервер и выпускать все между ними.

Edit 1 - Per Последующие вопрос, если вы хотите заменить все ссылки из массива URL-адресов с base64 кодировок, он может пойти что-то вроде этого (помните, что это может использовать много памяти):

- (void)base64ImagesAtUrls:(NSMutableArray *)urls result:(void (^)(void))completion { 

    __block NSInteger completed = 0; // this is how we'll know that we're done 
    // this approach doesn't depend on the asset library retrievals completing 
    // sequentially, even though they probably will 

    for (int i=0; i<urls.count; i++) { 
     NSString *urlString = urls[i]; 
     [self base64ImageAtUrlString:urlString result:^(NSString *base64) { 
      [urls replaceObjectAtIndex:i withObject:base64]; 
      if (++completed == urls.count) completion(); 
     }]; 
    } 
} 
+0

было очень полезно и информативно! Пока это работает !!! Итак, теперь у меня есть NSMutableArray, у которого есть все кодировки base64, как я могу заменить каждый urlRep на base64 в моем nmutable массиве? – BluGeni

+1

Помните, что замена url на base64-кодирование не экономит вам много памяти (всего несколько байтов, которые описывают URL-адрес), это просто заставляет вас потерять URL-адрес. Лучше было бы кодировать и отправлять по одному за раз. Если вам действительно нужны все кодировки в массиве, вы можете просто собрать их в новом изменяемом массиве (с addObject :). – danh

+0

да, это то, что я в конечном итоге делаю..и думаю .. Моя проблема в том, что (или что я считаю, проблема) Я пытаюсь setObject в словаре до того, как блок сделан. – BluGeni

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