setNeedsDisplayInRect: causes the whole view to be updated

后端 未结 4 1033
故里飘歌
故里飘歌 2020-12-08 23:54

I\'m working on a painting app that uses CoreGraphics for rendering. My problem is, for performance, I am trying to limit the updates to only certain portions of the view th

相关标签:
4条回答
  • 2020-12-09 00:13

    Check this apple document

    they said :

    because of the way that iPhone/iPod touch/iPad updates its screen, the entire view will be redrawn if you call -setNeedsDisplayInRect: or -setNeedsDisplay:.

    Also

    Each UIView is treated as a single element. When you request a redraw, in part or whole, by calling -setNeedsDisplayInRect: or -setNeedsDisplay:, the entire view will be marked for updates.

    so I think you need to use subviews to update independent rect of the whole View.

    0 讨论(0)
  • 2020-12-09 00:18

    I don't have a lot of devices available to me, but I have great news anyway! As someone who has been wishing for this functionality on iOS for years, I can assert that iOS8.0+ brings this functionality. I've tried on both simulator and device for 8.0, 8.1, 8.2

    I haven't tried this since iOS6. So I'm not sure if its available in iOS7 or not. Perhaps someone else can confirm.

    Please join with me in cheering endlessly for setNeedsDisplayInRect: functioning as documented!

    0 讨论(0)
  • 2020-12-09 00:30

    I have a similar issue: namely wanting to update only a portion of a UIView with a call to setNeedsDisplayInRect: which I pass a valid CGRect of the correct size (proved with Break Points, and Logs). Under iOS 4.2.1 (on my iPhone 3G) the UIView keeps its original image and only updates the portion specified by the CGRect, but under iOS 5.1 (on my iPhone 4S) the entire UIView is redrawn in transparent black (how black can be transparent is beyond me), with the area specified by the CGRect being drawn in correctly after. It seems to be either: an error on Apple's part that they are not implementing setNeedsDisplayInRect: correctly and just passing it to setNeedsDisplay:; or it was a wilful decision based on how the new iOS handles interaction with the actual screen architecture. Either way, it would seem that for the time being developers will either have to wear the cost of updating the entire UIView every time a graphical change occurs, or use some iOS detection and implement different screen drawing code depending on the iOS being dealt with.

    I have done some testing with the UIView property clearsContextBeforeDrawing (which according to the documentation should allow targeted drawing operations), but the results are identical for both YES and NO, so it would appear to be the implementation of the drawing code.

    As for the CGRect being of the incorrect size during updates: is it being set somewhere else prior to, or after, the drawing call. I set my CGRect just before the call to setNeedsDisplayInRect:, and then set it to CGRectNull on the last few lines of the drawRect method (this is so if the drawRect method is called by the system my code will not fire). After going back to your code snippet I can see it gets set in-line, which means it's a System Call that's redrawing the entire UIView, and hence why the CGRect is the entire view.

    I'll keep digging into this, but I fear that until Apple either disclose their reasoning for the change to setNeedsDisplayInRect:, or fix the apparent bug, we may be looking at updating the entire contents of a UIView for every graphical update (which could be potentially very 'expensive').

    0 讨论(0)
  • 2020-12-09 00:31

    The accepted answer is wrong (or at least misleading).

    Here's a simple code example of setNeedsDisplayInRect: working as advertised:

    http://charcoaldesign.co.uk/resources/chalkboard.zip

    I suspect that the Apple documentation is trying to explain the fact that on iOS every view backing image is converted to an OpenGL texture and the entire screen is re-composited every frame. That distinct from the question of whether your code has to clear and redraw the entire contents of the view's backing texture or not.

    By using setNeedsDisplayInRect: you can avoid expensive redrawing of content that doesn't change between frames (which uses core graphics and is not hardware accelerated). The whole screen will still be redrawn regardless, but that doesn't matter because it's hardware accelerated by the GPU, unlike the code in drawRect:

    0 讨论(0)
提交回复
热议问题