2015-06-12 5 views
32

Ich versuche, ein UIImage (wie ein Thumbnail oder etwas) von einem PHAsset zu erstellen, damit ich es in etwas übergeben kann, das ein UIImage nimmt. Ich habe versucht, Lösungen, die ich auf SO gefunden habe, zu adaptieren (da sie alle direkt in eine Tabellenansicht oder so weitergereicht werden), aber ich habe keinen Erfolg (wahrscheinlich, weil ich es nicht richtig mache).PHAsset zu 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 
} 

Die printlns sagen mir, dass die manager.request Linie gerade nichts tut. Wie bekomme ich es, um mir das Asset als UIImage zu geben?

Danke.

+0

Zum Beispiel, sagen, dass ich dies tun wollen: var image = a.getAssetThumbnail (firstAsset) Wie kann ich das erreichen? – dcheng

Antwort

62

Das tat, was ich brauchte, falls jemand das auch braucht.

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-Update

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

Wie würden Sie die ursprüngliche Breite + Höhe des PHAsset erhalten? –

+0

Ich frage mich auch, wie Sie die ursprüngliche Breite und Höhe erhalten, haben Sie eine Lösung gefunden, @TimNuwin? –

+1

Wenn Sie über die PixelWidth und PixelHeight Attribute sprechen, dann würden Sie das verwenden. Wenn nicht, würde ich etwas mehr Informationen benötigen, um zu helfen. Hoffentlich hilft dieser Link: https://developer.apple.com/library/ios/documentation/Photos/Reference/PHAsset_Class/ – dcheng

3

Das Problem ist, dass requestImageForAsset ein resultHandler ist und dieser Codeblock in der Zukunft passiert, nachdem Ihre Funktionen bereits gedruckt und den Wert zurückgegeben haben, den Sie erwarteten. Ich habe Änderungen vorgenommen, um Ihnen dies zu zeigen und einige einfache Lösungen vorzuschlagen.

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") 
} 

Erfahren Sie mehr über Schließungen und Fertigstellung Griff und async funcs bei Apple documentation

Ich hoffe, das hilft Ihnen!

+0

Noch irgendwie verwirrt. Also ändern wir getAssetThumbnail, um nichts zurückzugeben? In diesem Fall, wie werden wir das Retimage an das weitergeben, was wir brauchen? Wann und wie kann ich den Block zur Ausführung bringen, damit ich etwas Nützliches bekommen kann. Hoffentlich ist callReturnImage getrennt von der anderen Funktion versuchen wir retimage zu passieren. – dcheng

+0

Sie können nicht zurück etwas wie Ihre Rückkehr passieren wird, bevor Sie es abrufen, eine weitere Funktion hinzuzufügen, die das tun, was Sie mit dem Bild tun mögen, oder fügen Sie, was Sie in dem Abschluss-Block mit dem Bild machen wollen. Dies sind die zwei einfacheren Möglichkeiten, um dieses Problem zu beheben. – Icaro

+0

Rechts. Ok, sagen wir, ich habe 2 Funktionen (x & y), die beide UIImages nehmen. Ich möchte, dass sie auf der UII-Seite arbeiten, die wir in diesem Block erstellen. Ist es für mich unmöglich, dies außerhalb dieses Blocks zu tun, indem ich ein UIImage-Objekt in x & y übergebe und dieses Image von der Request-Methode abrufe? Oder muss ich x & y als CallReturnImage-Funktion setzen, die Sie angedeutet haben. Wenn es unmöglich ist, wenn ich Funktion z in der Zukunft erstellen würde, müsste ich nicht zurück gehen und diese Funktion bearbeiten, damit es funktioniert? – dcheng

4

Ich würde vorschlagen, mit Apples PHCachingImageManager (das erbt von PHImageManager):

Ein PHCachingImageManager Objekt abruft oder erzeugt Bilddaten für Foto oder Videoassets

Als o, PHCachingImageManager unterstützt einen besseren Caching-Mechanismus.

Beispiel einen Thumbnail-Synchron des Abrufens:

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* 
                } 

Darüber hinaus können Sie PHCachingImageManager zu Cache Ihrer Bilder für schnellere UI Antwort verwenden:

einen Caching-Bild-Manager verwenden:

  1. Erstellen Sie eine PHCachingImageManager-Instanz. (Dieser Schritt ersetzt die geteilt PHImageManager Instanz verwenden.)

  2. Verwenden PHAsset Klasse Methoden, um die Vermögenswerte zu holen Sie interessiert sind

  3. Zur Vorbereitung Bilder für diese Vermögenswerte, rufen Sie die startCachingImagesForAssets. TargetSize: contentMode: options: Methode mit der Zielgröße, dem Inhaltsmodus und den Optionen, die Sie verwenden möchten, wenn Sie später Bilder für jedes einzelne Asset anfordern.

  4. Wenn Sie ein Bild für einen einzelnen Vermögenswert benötigen, rufen Sie die requestImageForAsset: targetSize: contentMode: Optionen: resultHandler: Methode, und übergeben Sie die gleichen Parameter verwendet man, wenn das Asset vorbereitet.

Wenn das Bild, das Sie unter den bereits vorbereitet beantragen ist, das PHCachingImageManager Objekt zurückgibt sofort das Bild. Anderenfalls erstellt Photos das Bild auf Anforderung und speichert es für die spätere Verwendung .

In unserem Beispiel:

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

Für 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 
} 

Ressource: https://gist.github.com/lvterry/f062cf9ae13bca76b0c6#file-getassetthumbnail-swift

12

versuchen, dies es für mich funktioniert, hoffen, dass es Ihnen auch hilft,

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

Es hilft mir ..... –

+0

Ich bekomme den Fehler "Fehler beim Laden der Bilddaten für Asset " – Sneha

0

Objective-c-Version des Codes basiert auf Dcheng-Antwort.

-(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; 
    }