2011-08-26 19 views
6

Ho ricavato una classe da UIView, solo per rendermi conto che esistono delle limitazioni reali sulle sue dimensioni a causa della memoria. Ho questo UIView all'interno di UIScrollView.Evitare a UIView di creare una tela di disegno molto grande

C'è un modo per me di inserire qualcosa in una vista di scorrimento che non è una classe derivata da UIView ma in cui posso ancora disegnare e che può essere molto grande?

Non mi interessa dover rispondere agli eventi di rettangolo di esposizione, come si fa quando si utilizzano i sistemi di finestre convenzionali.

Grazie.

risposta

5

Le cose all'interno di un UIScrollView devono essere UIViews, le cui dimensioni sono limitate per motivi di memoria. UIView mantiene un backing store bitmap per motivi di prestazioni, quindi deve allocare memoria proporzionale alle sue dimensioni.

Il solito modo di gestirlo è generare più UIViews e scambiarli mentre l'utente scorre intorno. L'altra versione di questo è usare CATiledLayer. Nessuno di questi ti dà il modello di disegno "tela gigante", però. Spetta a te rompere le cose e disegnarle quando necessario. Questo è il solito approccio, però.

Se si desidera veramente una gigantesca tela, la mia raccomandazione sarebbe CGPDFContext. Per questi è disponibile un supporto avanzato, in particolare l'utilizzo di UIWebView (ricorda che è possibile aprire gli URI data: per evitare di leggere i file dal disco). E puoi disegnarne direttamente alcune parti applicando trasformazioni affini e poi CGContextDrawPDFPage. CGBitmapContext è un altro approccio, ma potrebbe richiedere molta più memoria per una piccola quantità di disegno.

2

modo da avere una UIView all'interno di un UIScrollView, ma volete che il vostro UIView di avere molto grandi limiti (cioè, in modo che corrisponda alle dimensioni di S' contentSize tuoi UIScrollView). Ma non vuoi disegnare l'intero UIView ogni volta che deve essere visualizzato, né puoi adattare l'intero contenuto alla memoria in una sola volta.

Fai la tua UIView utilizza un supporto CAScrollLayer, come segue:

// MyCustomUIView.m 

+ (Class) layerClass 
{ 
    return [CAScrollLayer class]; 
} 

aggiungere un metodo per aggiornare la posizione di scorrimento quando l'utente scorre il UIScrollView contenente il UIView:

// MyCustomUIView.m 

- (void) setScrollOffset:(CGPoint)scrollOffset 
{ 
    CAScrollLayer *scrollLayer = (CAScrollLayer*)self.layer; 

    [scrollLayer scrollToPoint:scrollOffset]; 
} 

Assicurarsi che quando disegni il tuo UIView, disegna solo le parti contenute nello CGRect a te fornite:

- (void)drawRect:(CGRect)rect 
{ 
    // Only draw stuff that lies inside 'rect' 
    // CGRectIntersection might be handy here! 
} 

Ora, nella vostra UIScrollViewDelegate, è necessario informare il CAScrollLayer vista sostenuta quando gli aggiornamenti genitore UIScrollView:

// SomeUIScrollViewDelegate.m 

- (void) scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    // Offset myCustomView within the scrollview so that it is always visible 
    myCustomView.frame = CGRectMake(scrollView.contentOffset.x, 
            scrollView.contentOffset.y, 
            scrollView.bounds.size.width, 
            scrollView.bounds.size.height); 

    // "Scroll" myCustomView so that the correct portion is rendered 
    [myCustomView setScrollOffset:self.contentOffset]; 

    // Tell it to update its display 
    [myCustomView setNeedsDisplay]; 
} 

È anche possibile utilizzare CATiledLayer, che è più facile perché non c'è bisogno di traccia la posizione di scorrimento - invece il tuo metodo drawRect verrà chiamato con ogni tessera come necessario. Tuttavia questo farà sì che la tua vista sbiadisca lentamente. Potrebbe essere utile se intendi memorizzare nella cache parti della tua vista e non preoccuparti dei lenti aggiornamenti.