2014-09-20 8 views
12

Sotto IOS 8 una chiamata al di UIViewCome prevenire il flash quando si chiama drawViewHierarchyInRect: afterScreenUpdates: su iOS 8?

[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES]; 

risultati in un fotogramma 1 lampo dell'immagine. Puoi vederlo per una frazione di secondo sullo schermo. Succede solo quando il parametro afterScreenUpdates è YES.

Questo è il mio codice completo per prendere screenshot:

UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, sf); 
CGContextRef ctx = UIGraphicsGetCurrentContext(); 
CGContextSaveGState(ctx); 
CGContextConcatCTM(ctx, [self.layer affineTransform]); 

if ([self respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { // iOS 7+ 
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES]; 
} else { // iOS 6 
    [self.layer renderInContext:ctx]; 
} 

UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 

CGContextRestoreGState(ctx); 
UIGraphicsEndImageContext(); 

C'è una soluzione?

+2

Phew, ho pensato che stavo impazzendo. Sto vedendo lo stesso problema, ma ho scoperto che succede solo su iPhone 6 (dispositivo e simulatore) e non particolarmente con iOS8. Sembra anche che accada con qualsiasi varietà di codice di istantanea che coinvolge afterScreenUpdates: YES. – Danny

+0

Posso confermare che il problema non si verifica su iPhone 5S. – iamjustaprogrammer

+0

Per me non è un "flash", ma piuttosto uno zoom molto veloce. Molto noioso. – afrederick

risposta

6

Fornire immagini di lancio @ 3x da utilizzare in iPhone6 ​​e iPhone6 ​​plus e questo problema va via.

+1

wow - non posso credere che funzioni, ma lo fa. –

+1

Confermato. Brillante! – shmim

+0

non ha funzionato per me – Rizon

2

Ecco una soluzione alternativa che ha risolto il problema.

Utilizzare CATransaction.completionBlock per chiamare UIView drawViewHierarchyInRect: afterScreenUpdates con il flag di aggiornamento schermo impostato su NO. L'ho usato per risolvere lo stesso problema. È semanticamente equivalente a impostare il flag su SÌ nel mio caso poiché sto solo invocandolo dopo l'attuale CATransaction è terminata e lo schermo è nello stato desiderato. Detto questo, nel mio caso, non ho alcuna animazione, quindi questo è praticamente immediato e cattura esattamente ciò che voglio. Se ci sono state animazioni, questo potrebbe non essere appropriato.

Per il mio caso, ho una vista di raccolta che è una raccolta di file. Ogni elemento è reso come un'istantanea di come appare il file una volta che l'utente lo apre. Alcuni file fanno sì che l'interfaccia utente abbia centinaia di livelli. Quando queste viste complicate venivano catturate, ottenevo uno schermo nero; o l'ultima/corrente animazione per rieseguire parzialmente. La mia vista collezione è w/in un controller di navigazione, stavo vedendo le repliche parziali dell'animazione pop. Ho anche notato repliche di animazioni di rotazione. Per i file più semplici, spesso non c'erano problemi. L'ho notato sul mio iPad Air (iOS 8.1) e su vari simulatori. Ho provato a mettere appIcons e launchImages sul posto ma non hanno avuto alcun effetto.

Ecco il codice originale. Inizializza un controller di visualizzazione, quindi aggiunge la vista del controller alla vista di utilità.

UIViewController *vlController = [[ComplicatedViewController alloc]init]; 
UIView *innerView = vlController.view; 
[v addSubview:innerView]; 
innerView.transform = CGAffineTransformMakeScale(scalar, scalar); 
innerView.center = CGRectCenterPoint(v.bounds); 
auto sz = v.bounds.size; 
innerView.bounds = {{0,0}, {sz.width/scalar, sz.height/scalar}}; 

UIGraphicsBeginImageContextWithOptions(v.bounds.size, YES, 0); 
[v drawViewHierarchyInRect:v.bounds afterScreenUpdates:YES]; 
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
[innerView removeFromSuperview]; 

UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 
[v addSubview:imageView]; 

Il nuovo codice sposta solo la metà inferiore al blocco di completamento di UIView animateWithDuration: completamento. Si noti che la durata dell'animazione UIView è 0, ma sembra che dia ancora quel ciclo di aggiornamento aggiuntivo per aggiornare lo schermo con la nuova interfaccia utente.

UIViewController *vlController = [[ComplicatedViewController alloc]init]; 
UIView *innerView = vlController.view; 
[UIView animateWithDuration:0.0 animations:^{ 
    [v addSubview:innerView]; 
    innerView.transform = CGAffineTransformMakeScale(scalar, scalar); 
    innerView.center = CGRectCenterPoint(v.bounds); 
    auto sz = v.bounds.size; 
    innerView.bounds = {{0,0}, {sz.width/scalar, sz.height/scalar}}; 
} completion:^(BOOL finished) {  
    UIGraphicsBeginImageContextWithOptions(v.bounds.size, YES, 0); 
    BOOL drawResult = [v drawViewHierarchyInRect:v.bounds afterScreenUpdates:NO]; 
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    [innerView removeFromSuperview]; 

    [self add:image forFile:v.filename withOrientation:v.orientation]; 
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 
    [v addSubview:imageView]; 
}]; 
+0

Questa soluzione sembra buona, ma ho bisogno di restituire UIImage nella mia funzione dal blocco di completamento. Mi sembra impossibile ... – RemembranceNN

Problemi correlati