2015-06-12 4 views
32

Я пытаюсь создать UIImage (как миниатюру или что-то еще) из PHAsset, чтобы я мог передать его во что-то, что принимает UIImage. Я пробовал адаптировать решения, которые я нашел на SO (поскольку они просто прямо передают его в виде табличного представления или что-то в этом роде), но у меня нет успеха (скорее всего, потому что я не делаю это правильно).PHAsset to UIImage

func getAssetThumbnail(asset: PHAsset) -> UIImage { 
    var retimage = UIImage() 
    println(retimage) 
    let manager = PHImageManager.defaultManager() 
    manager.requestImageForAsset(asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .AspectFit, options: nil, resultHandler: {(result, info)->Void in 
      retimage = result 
    }) 
    println(retimage) 
    return retimage 
} 

Печатные издания говорят мне, что строка manager.request ничего не делает прямо сейчас. Как мне получить его, чтобы дать мне актив как UIImage.

Спасибо.

+0

Например, сказать, что я хочу сделать это: вар изображение = a.getAssetThumbnail (firstAsset) Как я могу добиться этого? – dcheng

ответ

62

Это сделало то, что мне было нужно для этого, в случае, если кому-то это тоже понадобится.

func getAssetThumbnail(asset: PHAsset) -> UIImage { 
    let manager = PHImageManager.defaultManager() 
    let option = PHImageRequestOptions() 
    var thumbnail = UIImage() 
    option.synchronous = true 
    manager.requestImageForAsset(asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .AspectFit, options: option, resultHandler: {(result, info)->Void in 
      thumbnail = result! 
    }) 
    return thumbnail 
} 

Edit: Swift 3 обновление

func getAssetThumbnail(asset: PHAsset) -> UIImage { 
    let manager = PHImageManager.default() 
    let option = PHImageRequestOptions() 
    var thumbnail = UIImage() 
    option.isSynchronous = true 
    manager.requestImage(for: asset, targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in 
     thumbnail = result! 
    }) 
    return thumbnail 
} 
+4

Как бы вы получили исходную ширину + высоту PHAsset? –

+0

Мне также интересно, как получить оригинальную ширину и высоту, нашли ли вы решение, @TimNuwin? –

+1

Если вы говорите об атрибутах pixelWidth и pixelHeight, то это то, что вы будете использовать. Если нет, мне нужно немного больше информации, чтобы помочь. Надеюсь, эта ссылка поможет: https://developer.apple.com/library/ios/documentation/Photos/Reference/PHAsset_Class/ – dcheng

3

Проблема заключается в том, что requestImageForAsset является результатомHandler, и этот блок кода происходит в будущем после того, как ваши функции уже были напечатаны и вернули ожидаемое значение. Я пришел к изменениям, чтобы показать вам это, а также предложить некоторые простые решения.

func getAssetThumbnail(asset: PHAsset) { 
    var retimage = UIImage() 
    println(retimage) 
    let manager = PHImageManager.defaultManager() 
    manager.requestImageForAsset(asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .AspectFit, options: nil, resultHandler: { 
    (result, info)->Void in 
      retimage = result 
     println("This happens after") 
     println(retimage) 
     callReturnImage(retimage) // <- create this method 
    }) 
    println("This happens before") 
} 

Узнайте больше о замыканиях и завершения ручки и асинхронными funcs на Apple documentation

Я надеюсь, что поможет вам!

+0

Все еще любопытное смущение. Итак, мы меняем getAssetThumbnail, чтобы ничего не вернуть? В этом случае, как мы собираемся пройти повторный сбор до того, что нам нужно? Когда и как я могу заставить блок выполнить, чтобы я мог получить что-то полезное. Надеюсь, callReturnImage отделен от другой функции, с которой мы пытаемся передать retimage. – dcheng

+0

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

+0

Справа. Ok позволяет сказать, что у меня есть 2 функции (x & y), которые берут UIImages. Я хочу, чтобы они работали над UIImage, который мы создаем в этом блоке. Невозможно ли я сделать это за пределами этого блока, передав UIImage в x & y и получив это изображение из метода запроса? Или мне нужно поставить x & y как функцию callReturnImage, которую вы намекали. Если это невозможно, то если бы я должен был создать функцию z в ​​будущем, мне не нужно было возвращаться и редактировать эту функцию, чтобы она работала? – dcheng

4

я предлагаю использовать Apple, PHCachingImageManager (который наследует от PHImageManager):

PHCachingImageManager объект получает или генерирует данные изображения для фото или видеооборудование

Als o, PHCachingImageManager поддерживает лучший механизм кэширования.

Пример извлечения синхронные миниатюру:

let options = PHImageRequestOptions() 
options.deliveryMode = .HighQualityFormat 
options.synchronous = true // Set it to false for async callback 

let imageManager = PHCachingImageManager() 
imageManager.requestImageForAsset(YourPHAssetVar, 
            targetSize: CGSizeMake(CGFloat(160), CGFloat(160)), 
            contentMode: .AspectFill, 
            options: options, 
            resultHandler: { (resultThumbnail : UIImage?, info : [NSObject : AnyObject]?) in 

                // Assign your thumbnail which is the *resultThumbnail* 
                } 

Кроме того, вы можете использовать PHCachingImageManager в кэш изображений для быстрого ответа UI:

использовать менеджер кэширования изображения:

  1. Создайте экземпляр PHCachingImageManager. (Этот шаг заменяет используя общий экземпляр PHImageManager.)

  2. методы класса Использование PHAsset для извлечения активов вы заинтересованы в

  3. Чтобы подготовить изображения для этих активов, называют startCachingImagesForAssets:. TargetSize: contentMode: options: метод с целевым размером, режимом содержимого и параметрами, которые вы планируете использовать, когда позже запрашивает изображения для каждого отдельного актива.

  4. При необходимости изображение для отдельного актива, вызовите requestImageForAsset: targetSize: contentMode: варианты: ResultHandler: метод, и передать те же параметры, используемые при подготовке, что актива.

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

В нашем примере:

var phAssetArray : [PHAsset] = [] 

for i in 0..<assets.count 
{ 
    phAssetArray.append(assets[i] as! PHAsset) 
} 

let options = PHImageRequestOptions() 
options.deliveryMode = .Opportunistic 
options.synchronous = false 

self.imageManager.startCachingImagesForAssets(phAssetArray, 
               targetSize: CGSizeMake(CGFloat(160), CGFloat(160)), 
               contentMode: .AspectFill, 
               options: options) 
6

Для Swift 3.0.1:

func getAssetThumbnail(asset: PHAsset, size: CGFloat) -> UIImage { 
    let retinaScale = UIScreen.main.scale 
    let retinaSquare = CGSize(width: size * retinaScale, height: size * retinaScale)//(size * retinaScale, size * retinaScale) 
    let cropSizeLength = min(asset.pixelWidth, asset.pixelHeight) 
    let square = CGRect(x:0, y: 0,width: CGFloat(cropSizeLength),height: CGFloat(cropSizeLength)) 
    let cropRect = square.applying(CGAffineTransform(scaleX: 1.0/CGFloat(asset.pixelWidth), y: 1.0/CGFloat(asset.pixelHeight))) 

    let manager = PHImageManager.default() 
    let options = PHImageRequestOptions() 
    var thumbnail = UIImage() 

    options.isSynchronous = true 
    options.deliveryMode = .highQualityFormat 
    options.resizeMode = .exact 
    options.normalizedCropRect = cropRect 

    manager.requestImage(for: asset, targetSize: retinaSquare, contentMode: .aspectFit, options: options, resultHandler: {(result, info)->Void in 
     thumbnail = result! 
    }) 
    return thumbnail 
} 

Ресурс: https://gist.github.com/lvterry/f062cf9ae13bca76b0c6#file-getassetthumbnail-swift

12

попробовать это работает для меня, надеюсь, что это поможет вам тоже,

func getUIImage(asset: PHAsset) -> UIImage? { 

    var img: UIImage? 
    let manager = PHImageManager.default() 
    let options = PHImageRequestOptions() 
    options.version = .original 
    options.isSynchronous = true 
    manager.requestImageData(for: asset, options: options) { data, _, _, _ in 

     if let data = data { 
      img = UIImage(data: data) 
     } 
    } 
    return img 
} 
+1

Это помогает мне ..... –

+0

Я получаю сообщение об ошибке «Не удалось загрузить данные изображения для актива » – Sneha

0

Objective-c версия кода на основе ответа dcheng.

-(UIImage *)getAssetThumbnail:(PHAsset *)asset { 

    PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init]; 
    options.synchronous = true; 

    __block UIImage *image; 
    [PHCachingImageManager.defaultManager requestImageForAsset:asset targetSize:CGSizeMake(100, 100) contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { 
     image = result; 
    }]; 
    return image; 
    }