tags:

views:

3650

answers:

6

I'm trying to draw a graph that is indefinitely large horizontally, and the same height as the screen. I've added a UIScrollView, and a subclass of a UIView within it, which implements the -drawRect: method. In the simulator, everything works fine, but on the device, it can't seem to draw the graph after it reaches a certain size.

I'm already caching pretty much everything I can, and basically only calling CGContextAddLineToPoint in the -drawRect: section. I'm only drawing what's visible on the screen. I have a delegate to the UIScrollView which listens for -scrollViewDidScroll: which then tells the graph to redraw itself ([graphView setNeedsDisplay]).

I found one method that tells me to override the +layerClass method and return [CATiledLayer class]. This does allow the graph to actually draw on the device, but it functions very poorly. It's incredibly slow to actually draw, and the fade in that occurs is undesirable.

Any suggestions?

+1  A: 

I think this is a limitation of the iPhone graphics hardware. Through experimentation, I have seen that the iPhone will refuse to draw a frame that is bigger than 2000 pixels in either height or width. It probably has something to do with limited size for frame buffers in hardware.

Marc Novakowski
Not a very useful answer, I think. There's obviously a way to do this, since things like Google Maps seem to be able to work just fine. Not choppy at all, and seems to be pretty good at drawing quickly, even when it has to download the data first.
Ed Marty
I'm just saying that you can't do it within a single UI control because its frame will be too big. There's probably a way you can place multiple views together horizontally but you're probably going to have to manage them yourself (destroying/creating on the fly).
Marc Novakowski
+3  A: 

Well, here's my answer: I basically did something similar to how the UITableView works with cells: I have an NSMutableSet of GraphView objects which store unused graphs. When a section of the scroll view becomes visible, I take a graph view from that set (or make a new one if the set is empty). It already had a scrollX property to determine which part of it was supposed to draw. I set the scrollX property to the correct value and, instead of using the screen width, I gave it an arbitrary width to draw. When it goes out of the scroll view, it is removed from the UIScrollView and added to the set.

I wonder though if I really even need to remove them when they go outof the view? It may be prudent to try leaving them in and remove the ones not on screen only if I get a low memory warning? This might get rid of the pause whenever it needs to redraw a section of graph that hasn't changed.

My saving grace here was that my GraphView already was set up to draw only a portion of the graph. All I needed to do then was just make more than one of them.

Ed Marty
A: 

I would like to do the same thing, displaying an indefinite ruler, do you have a sample code ?

Thanks a lot

I don't have code here, but:Every time you scroll, find the scroll position, divide by the width of each piece, and determine which pieces are shown. Remove the hidden ones, (add them to a cache of objects, i.e. NSMutableSet) and add new ones taken from that set, or create new ones if it's empty.
Ed Marty
A: 

Thanks, that's helpful. One question -- what did you use for the contentSize of the UIScrollView? Does UIScrollView tolerate large content sizes (over 2000 px) as long as you're not creating buffers to fill the entire space in your content view? Or are you keeping the UIScrollView a constant size (say, 2 screen widths) and resting the UIScrollView contentOffset property each time you draw (using scrollX instead of the contentOffset to store your position)?

I think I answered my own question (the latter seems like a better alternative), heh, but I'll go ahead and post this in case other people need clarification.

The contentSize is as large as it needs to be (as wide as 50500 pixels in my case), with many different views inside it
Ed Marty
Have you experimented with storing just a CGLayer and a CGPoint objects for each cache instead of an entire view? I'm thinking it would reduce overhead, but I'm not sure if it would make much of a difference.
On second thought, that wouldn't work because a CGLayer needs to be drawn into some context, so you still need a UIView to draw into. Nevermind.
A: 

Wherever they say of infinite scrolling, people keeps telling of setting the contentOffSet. But yet I dont get how to re-adjust it. I have got a scrollView with screen size and contentSize(1280 1280).Have placed 25 images(256 256) in it. When i move to any direction it should appear as infinite and I have images to be placed wherever I move.///r to mapView. But cant get the idea how to do this and how to adjust the contentOffset so that after dragging when i stop, It should be the new position. Plz answer my doubt.

wolverine
A: 

Ed, I ran across your post because I'm doing trying to do the same thing that you did with your graph app (draw what is to be shown and add to the objects pool those that are not being displayed). The problem I'm running though is that if I scroll really fast horizontally my views don't get drawn on time and you can see the UIScrollView's background. Did you run across this same problem? What did you do to solve it? Any ideias?

fbr

ForeignerBR