开发者

What is the proper way to make it so core graphics does not lag?

开发者 https://www.devze.com 2023-04-10 07:55 出处:网络
I use UIBezierPath for finger painting (my app). I create it using path = [UIBezierPath bezier path]; . It constantly lags on the iPad (and calling it from within drawrect did not change anything). I

I use UIBezierPath for finger painting (my app). I create it using path = [UIBezierPath bezier path]; . It constantly lags on the iPad (and calling it from within drawrect did not change anything). I have been working on this for hours on end and have found no solution, just lag. Would somebody be so kind to help me please? Also, I am using a NSTimer to call the function. That is the old way my app will work so please he开发者_如何转开发lp me fix this lagggg!!!!!


Since none of your questions contains enough details on its own, I'm going to do something improper and post a meta-answer to your current last five questions.

First, draw in drawRect: and nowhere else.

That's so important that I'm going to say it again.

Draw in drawRect: and nowhere else.

Not touchesMoved:withEvent:.

Not touchesBegan: or Ended:.

drawRect: and nowhere else.

If you're making an image to save to a file, that's one thing. But when you're drawing to the screen, you don't do it anywhere other than drawRect:.

Seriously. It's that important.

Step 2: Don't attempt to force drawing to happen at any other time.

drawRect: is called for you when it's time for you to draw. By definition, at any other time, you don't need to draw, so drawing is doing things you don't need to do. By extension, don't call drawRect: yourself. You don't need to and it never helps.

Actually, that's just an extension of step 1. If you call drawRect:, it's no different from if you had the drawing code where you have the call. The drawing code isn't repeated everywhere, which is nice, but it's still running at the wrong time. Let drawRect: only be called when the system calls it.

setNeedsDisplay exists to tell the system that it's time to draw. You should do this when, and only when, something has changed that you'll need to draw. Your view's properties, something in the model—whenever what you will draw changes, send yourself setNeedsDisplay. Don't do it at any other time; you don't need to.

Cut out the timer. You don't need it. There's already a timer in place anyway, limiting you to 60 fps.

Core Graphics does not lag. No, really, it doesn't. Slowness or “lag” is because either you're trying to do too much or you're doing something wrong.

Don't cache unnecessarily. Nothing you're doing requires an image cache.

The “lag” is because you're trying to draw, or to force drawing, from touchesMoved:withEvent: and/or touchesBegan:/Ended:. See above.


Here's what you need to do:

In your touchesBegan:/Moved:/Ended: methods, or other responder methods as appropriate, update your state. This will include the Bézier path. Do not draw, and that includes do not call drawRect: or otherwise attempt to force drawing.

After you've updated your state, and only if you've done so, send yourself setNeedsDisplay.

In your drawRect: method, and only in your drawRect: method, draw the path, gradient, whatever, however you see fit.

Do these things, and your application will be fast. With Core Graphics. Without lag.


Also, some important reading:

  • View Programming Guide for iOS
  • Drawing … Programming Guide for iOS
  • Quartz 2D (Core Graphics) Programming Guide
  • Performance Overview (some parts are Mac OS X specific, but much of it is relevant on iOS as well)
  • Instruments User Guide


don't use a timer to periodically redraw when your view must be redrawn based on response to user events.

instead, invalidate your view using setNeedsDisplay or setNeedsDisplayInRect: when you receive touches which require you to redraw portions of your view.

a complex touch drawing iPad app can be a lot to ask to render in realtime, especially when you are overdrawing. draw only when needed.

another option: work in layers

you probably don't have undo in your app, so it should be simple to implement. periodically composite your image down to a single view. when draw rect is called, you then have fewer paths to draw (1 large image + fewer paths). in that case, a cached backing bitmap would definitely help.

again, there's not a whole lot of detail in your posts, and you haven't told us what the profiler is showing you.

0

精彩评论

暂无评论...
验证码 换一张
取 消