2014-12-27 2 views
19

So verwende ich die SwipeView-Bibliothek (https://github.com/nicklockwood/SwipeView), um Bilder mit dem Photos-Framework für iOS8 anzuzeigen.Fotos Rahmen. requestImageForAsset gibt zwei Ergebnisse zurück. Die Bildansicht kann nicht eingestellt werden

Allerdings, wenn ich den requestImageForAsset aufrufen merke ich, dass ich zwei Ergebnisse, eine Miniaturgröße und die größere Größe, die ich will. Das größere Bild wird jedoch nicht geladen (es heißt Async, das ich verstehe), damit es zurückkehrt, also gibt es das kleine Bild zurück.

Dieser Code könnte mehr Sinn machen.

func swipeView(swipeView: SwipeView!, viewForItemAtIndex index: Int, reusingView view: UIView!) -> UIView! { 
      let asset: PHAsset = self.photosAsset[index] as PHAsset 

    var imageView: UIImageView! 

    let screenSize: CGSize = UIScreen.mainScreen().bounds.size 
    let targetSize = CGSizeMake(screenSize.width, screenSize.height) 


    var options = PHImageRequestOptions() 
//  options.deliveryMode = PHImageRequestOptionsDeliveryMode.Opportunistic 
    options.resizeMode = PHImageRequestOptionsResizeMode.Exact 


    PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options, resultHandler: {(result, info)in 
     println("huhuhuh") 
     println(result.size) 
     println(info) 
     imageView = UIImageView(image: result) 
    }) 
    println("setting view) 
    return imageView 
} 

Hier ist die Log-Ausgabe:

Enteredhuhuhuh 
(33.5,60.0) 
SETTING VIEW 
huhuhuh 
(320.0,568.0) 

Wie Sie es gibt die Bildansicht vor dem großen Bild empfangen wird, sehen. Wie kann ich dieses größere Bild zurückgeben, so dass es die thumbnail nicht zeigt?

Danke.

+1

Haben Sie dieses Problem gelöst? – Mrunal

Antwort

65

Lesen Header PHImageManager Klasse

Wenn - [PHImageRequestOptions isSynchronous] NEIN zurückgibt (oder Optionen ist nil), kann resultHandler 1 oder mehrmals aufgerufen werden. In diesem Fall wird resultHandler asynchron auf dem Hauptthread mit den angeforderten Ergebnissen aufgerufen. Wenn jedoch deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic ist, kann resultHandler synchron mit dem aufrufenden Thread aufgerufen werden, wenn Bilddaten sofort verfügbar sind. Wenn die Bilddaten, die in diesem ersten Durchlauf zurückgegeben werden, von unzureichender Qualität sind, wird resultHandler erneut asynchron zum Hauptthread zu einem späteren Zeitpunkt mit den "korrekten" Ergebnissen aufgerufen, . Wenn die Anfrage abgebrochen wird, kann resultHandler nicht überhaupt aufgerufen werden. Wenn - [PHImageRequestOptions isSynchronous] den Wert YES zurückgibt, wird resultHandler genau einmal synchron und im aufrufenden Thread aufgerufen. Synchrone Anfragen können nicht abgebrochen werden. resultHandler für asynchrone Anforderungen, immer auf Hauptthread genannt

Also, was Sie tun möchten, ist, dass Sie resultHandler machen aufgerufen werden synchronously

PHImageRequestOptions *option = [PHImageRequestOptions new]; 
option.synchronous = YES; 

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:target contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) { 
     //this block will be called synchronously 
}]; 

So wird dem Block vor dem Ende aufgerufen werden Ihre Methode

Viel Glück!

+1

Ich denke, VietHung hat die richtige Antwort. Wählen Sie die Option Synchron aus, um die Rückkehr zum Bild mit voller Auflösung zu erzwingen. Andernfalls können Sie den Code so belassen, wie er ist, und zuerst das Miniaturbild mit niedriger Auflösung anzeigen und später den zweiten Aufruf des Blocks zulassen, um das Bild in Ihrer Bildansicht zu aktualisieren. Dies ist wahrscheinlich der Grund, warum Apple den Callback für den Haupt-Thread ausgeführt hat, so dass Sie alle gewünschten Updates durchführen können, sobald das vollständige Res Image verfügbar ist. –

+0

Wenn du letzteres gehst, rufe vielleicht setNeedsDisplay auf der imageView im Block auf und schau was passiert. –

+0

Arbeitete am besten, vielen Dank! – Jonovono

1

Überprüfen Sie die Apple-Dokumentation für diese Methode here. In, dass sie sagen:

Für eine asynchrone Anforderung, Fotos aufrufen kann Ihr Ergebnis Handler mehr als einmal blockieren. Fotos ruft zuerst den Block an, um ein Bild von niedriger Qualität zu liefern, das für die zeitweilige Anzeige geeignet ist, während es ein hochwertiges Bild vorbereitet. (Wenn minderwertige Bilddaten sofort verfügbar, der erste Aufruf, bevor die Methode zurückgibt, auftreten können.)

Es könnte zum Abrufen von Originalgröße Bild Zeit, in Ihrem Fall nehmen. Sonst scheint mir dein Code in Ordnung zu sein.

1

Sie sollten ImageView innerhalb Block nicht umschreiben, nur Bild darauf setzen und alles sollte so funktionieren, wie Sie es erwarten. Um zu vermeiden, dass zwei Bilder angezeigt werden, können Sie die Größe des Bildes vor der Zuweisung überprüfen.

var imageView = UIImageView() 
... 
... 
     PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options, resultHandler: {(result, info)in 
       println("huhuhuh") 
       println(result.size) 
       println(info) 
       if result.size.width > 1000 && result.size.height > 1000 { // add any size you want 
        imageView.setImage(result) 
       } 
      }) 
+0

uhhh, diese Art Lösung ist ein Hack, der wirklich unzuverlässig ist, siehe die akzeptierte Antwort für eine gute Annäherung –

4

Standardmäßig funktioniert requestImageForAsset asynchron. Daher wird die return-Anweisung in Ihrer Methode ausgeführt, noch bevor das Bild abgerufen wird. Also mein Vorschlag ist, anstatt die Imageview zurückzukehren, übergeben Sie die Imageview, dass Sie das Bild füllen müssen:

func swipeView(swipeView: SwipeView!, viewForItemAtIndex index: Int, reusingView view: UIView!, yourImageView: UIImageView) 
{ 
    let asset: PHAsset = self.photosAsset[index] as PHAsset 

    var imageView: UIImageView! = yourImageView; 

    let screenSize: CGSize = UIScreen.mainScreen().bounds.size 
    let targetSize = CGSizeMake(screenSize.width, screenSize.height) 


    var options = PHImageRequestOptions() 
    options.resizeMode = PHImageRequestOptionsResizeMode.Exact 

    PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options, resultHandler: {(result, info)in 
     imageView.image = result; 
    }) 
} 

Hinweis:

Eine weitere Option ist, können Sie eine Benachrichtigung mit dem Ergebnisbild Feuer aus das ErgebnisHandler. Aber ich bevorzuge die oben erwähnte Methode.

Weitere Informationen finden Sie unter PHImageManager.

4

resultHandler: Block verfügt über ein Infowörterbuch, das einen booleschen Wert für PHImageResultIsDegradedKey enthält, der angibt, ob das Ergebnisbild ein minderwertiger Ersatz für das angeforderte Bild ist.

Hier ist, was Dokumentation sagt:

PHImageResultIsDegradedKey: Ein boolescher Wert, den angibt, ob das Ergebnisbild ist ein minderwertiger Ersatz für das angeforderte Bild. (NSNumber)

Wenn JA, enthält das Ergebnisparameter Ihres resultHandler Block ein minderwertiges Bild, weil Fotos Bild mit höherer Qualität noch nicht konnten bieten. Abhängig von Ihren Einstellungen im PHImageRequestOptions-Objekt, das Sie mit der Anforderung angegeben haben, können die Fotos Ihren Ergebnis-Handler-Block erneut aufrufen, um ein Bild mit höherer Qualität bereitzustellen.

+0

Der Wert für den Schlüssel PHImageResultIsDegradedKey ist in einer solchen Situation falsch –

0

versuchen, dies funktioniert auch asynchron.

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:target contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) { 
    if ([info objectForKey:@"PHImageFileURLKey"]) { 
     //your code 
    } 
}]; 
0

Verwenden Sie den folgenden Optionen, schnelle 3,0

publi var imageRequestOptions: PHImageRequestOptions{ 
let options = PHImageRequestOptions() 
options.version = .current 
options.resizeMode = .exact 
options.deliveryMode = .highQualityFormat 
options.isNetworkAccessAllowed = true 
options.isSynchronous = true 
return options} 
Verwandte Themen