Re: UIView underlying rects for drawRect

2015-12-07 Thread David Duncan

> On Dec 6, 2015, at 4:51 AM, Roland King  wrote:
> 
>> 
>> On 6 Dec 2015, at 20:18, Roland King  wrote:
>> 
>> 
>>> 
>>> CALayer has a mechanism built in for the sort of thing you want to do. Read 
>>> up on -[CALayer display]. You should be able to override that, or implement 
>>> the corresponding delegate method in your UIView and perform management of 
>>> your custom bitmap there. I myself do this in one app to share one bitmap 
>>> between multiple layers for example.
>>> 
>>> The other thing worth investigating perhaps is whether CATiledLayer would 
>>> better suit your drawing needs, or if you could split your custom view up 
>>> into a series of sub-views, so you only need invalidate slices of one or 
>>> two of them.
>>> 
>>> Mike.
>> 
>> That’s what I was just trying. I made a subclass of CALayer() and overrode 
>> just display() to do absolutely nothing at all, except print ‘display()’. I 
>> then made a UIView subclass which overrides layerClass() to return the type 
>> and stuck one such view randomly in my NIB. The view is made, the layer is 
>> created .. and absolutely nothing else happens. I expected to get at least 
>> ONE call to display() as the view/layer starts dirty, but I don’t get even 
>> that. I even hooked up a button to call setNeedsDisplay on the view but that 
>> didn’t prompt it either. I overrode a bunch of other methods too to print 
>> but the only one which currently gets called is init(). 
>> 
>> I expected the UIView would drive at least an initial setNeedsDisplay on the 
>> layer, and a setNeedsDisplay on the view would end up being passed-through, 
>> but it doesn’t. Calling setNeedsDisplay on the actual layer object itself 
>> seems to work, but I did sort of expect the UIView to do some things with 
>> the layer automatically. Guess I was wrong and I will need to hook all those 
>> bits up for myself. 
> 
> ok I begin to see how it all works now. So if the layer is the view’s layer, 
> instead of a separate totally custom layer you add to the layer, then the 
> view sets some things on it but not everything. It turns off 
> needsDisplayOnBoundsChange (which I had set on init in the layer) unless the 
> view’s contentMode is redraw, which somewhat confused me. That causes the 
> layer to call display() on itself on bounds change. However it doesn’t pass 
> setNeedsDisplay() and setNeedsDisplayInRect() through to the underlying layer 
> which I’d have expected. I assume it only calls those that if the layer is a 
> normal UIView layer and not a custom one. 

UIView will not dirty its layer if your subclass does not implement -drawRect:.

> 
> I think as long as that’s the extent of its meddling with ‘its layer’, just 
> setting a few properties when it starts up and adjusting the bounds for me, I 
> can live with it. I’ll try out a few more things on the view to see if there 
> are other things I need to be prepared to deal with, just having it manage 
> the layer bounds automatically is helpful if that’s about all it does. 
> 
> 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/david.duncan%40apple.com
> 
> This email sent to david.dun...@apple.com

--
David Duncan

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: UIView underlying rects for drawRect

2015-12-07 Thread Roland King

> On 8 Dec 2015, at 06:30, David Duncan  wrote:
> 
>> 
>> On Dec 6, 2015, at 4:51 AM, Roland King > > wrote:
>> 
>>> 
>>> On 6 Dec 2015, at 20:18, Roland King > 
>>> wrote:
>>> 
>>> 
 
 CALayer has a mechanism built in for the sort of thing you want to do. 
 Read up on -[CALayer display]. You should be able to override that, or 
 implement the corresponding delegate method in your UIView and perform 
 management of your custom bitmap there. I myself do this in one app to 
 share one bitmap between multiple layers for example.
 
 The other thing worth investigating perhaps is whether CATiledLayer would 
 better suit your drawing needs, or if you could split your custom view up 
 into a series of sub-views, so you only need invalidate slices of one or 
 two of them.
 
 Mike.
>>> 
>>> That’s what I was just trying. I made a subclass of CALayer() and overrode 
>>> just display() to do absolutely nothing at all, except print ‘display()’. I 
>>> then made a UIView subclass which overrides layerClass() to return the type 
>>> and stuck one such view randomly in my NIB. The view is made, the layer is 
>>> created .. and absolutely nothing else happens. I expected to get at least 
>>> ONE call to display() as the view/layer starts dirty, but I don’t get even 
>>> that. I even hooked up a button to call setNeedsDisplay on the view but 
>>> that didn’t prompt it either. I overrode a bunch of other methods too to 
>>> print but the only one which currently gets called is init(). 
>>> 
>>> I expected the UIView would drive at least an initial setNeedsDisplay on 
>>> the layer, and a setNeedsDisplay on the view would end up being 
>>> passed-through, but it doesn’t. Calling setNeedsDisplay on the actual layer 
>>> object itself seems to work, but I did sort of expect the UIView to do some 
>>> things with the layer automatically. Guess I was wrong and I will need to 
>>> hook all those bits up for myself. 
>> 
>> ok I begin to see how it all works now. So if the layer is the view’s layer, 
>> instead of a separate totally custom layer you add to the layer, then the 
>> view sets some things on it but not everything. It turns off 
>> needsDisplayOnBoundsChange (which I had set on init in the layer) unless the 
>> view’s contentMode is redraw, which somewhat confused me. That causes the 
>> layer to call display() on itself on bounds change. However it doesn’t pass 
>> setNeedsDisplay() and setNeedsDisplayInRect() through to the underlying 
>> layer which I’d have expected. I assume it only calls those that if the 
>> layer is a normal UIView layer and not a custom one. 
> 
> UIView will not dirty its layer if your subclass does not implement 
> -drawRect:.
> 

Ah - thanks - that’s a useful missing piece to know. I’m fairly happy now that 
my layer is doing what its owning UIView expects and I’m getting better 
performance with less CPU. Instruments has been great for this too, couple of 
hours looking at the heavy stack traces and watching how CPU usage changed over 
time, a few targetted tweaks to code I expected was going to need some kind of 
optimisation, I’m using about 10% of the power I was at the weekend. Good 
stuff. 
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: UIView underlying rects for drawRect

2015-12-06 Thread Roland King

> 
> CALayer has a mechanism built in for the sort of thing you want to do. Read 
> up on -[CALayer display]. You should be able to override that, or implement 
> the corresponding delegate method in your UIView and perform management of 
> your custom bitmap there. I myself do this in one app to share one bitmap 
> between multiple layers for example.
> 
> The other thing worth investigating perhaps is whether CATiledLayer would 
> better suit your drawing needs, or if you could split your custom view up 
> into a series of sub-views, so you only need invalidate slices of one or two 
> of them.
> 
> Mike.

That’s what I was just trying. I made a subclass of CALayer() and overrode just 
display() to do absolutely nothing at all, except print ‘display()’. I then 
made a UIView subclass which overrides layerClass() to return the type and 
stuck one such view randomly in my NIB. The view is made, the layer is created 
.. and absolutely nothing else happens. I expected to get at least ONE call to 
display() as the view/layer starts dirty, but I don’t get even that. I even 
hooked up a button to call setNeedsDisplay on the view but that didn’t prompt 
it either. I overrode a bunch of other methods too to print but the only one 
which currently gets called is init(). 

I expected the UIView would drive at least an initial setNeedsDisplay on the 
layer, and a setNeedsDisplay on the view would end up being passed-through, but 
it doesn’t. Calling setNeedsDisplay on the actual layer object itself seems to 
work, but I did sort of expect the UIView to do some things with the layer 
automatically. Guess I was wrong and I will need to hook all those bits up for 
myself. 
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: UIView underlying rects for drawRect

2015-12-06 Thread Roland King

> On 6 Dec 2015, at 20:18, Roland King  wrote:
> 
> 
>> 
>> CALayer has a mechanism built in for the sort of thing you want to do. Read 
>> up on -[CALayer display]. You should be able to override that, or implement 
>> the corresponding delegate method in your UIView and perform management of 
>> your custom bitmap there. I myself do this in one app to share one bitmap 
>> between multiple layers for example.
>> 
>> The other thing worth investigating perhaps is whether CATiledLayer would 
>> better suit your drawing needs, or if you could split your custom view up 
>> into a series of sub-views, so you only need invalidate slices of one or two 
>> of them.
>> 
>> Mike.
> 
> That’s what I was just trying. I made a subclass of CALayer() and overrode 
> just display() to do absolutely nothing at all, except print ‘display()’. I 
> then made a UIView subclass which overrides layerClass() to return the type 
> and stuck one such view randomly in my NIB. The view is made, the layer is 
> created .. and absolutely nothing else happens. I expected to get at least 
> ONE call to display() as the view/layer starts dirty, but I don’t get even 
> that. I even hooked up a button to call setNeedsDisplay on the view but that 
> didn’t prompt it either. I overrode a bunch of other methods too to print but 
> the only one which currently gets called is init(). 
> 
> I expected the UIView would drive at least an initial setNeedsDisplay on the 
> layer, and a setNeedsDisplay on the view would end up being passed-through, 
> but it doesn’t. Calling setNeedsDisplay on the actual layer object itself 
> seems to work, but I did sort of expect the UIView to do some things with the 
> layer automatically. Guess I was wrong and I will need to hook all those bits 
> up for myself. 

ok I begin to see how it all works now. So if the layer is the view’s layer, 
instead of a separate totally custom layer you add to the layer, then the view 
sets some things on it but not everything. It turns off 
needsDisplayOnBoundsChange (which I had set on init in the layer) unless the 
view’s contentMode is redraw, which somewhat confused me. That causes the layer 
to call display() on itself on bounds change. However it doesn’t pass 
setNeedsDisplay() and setNeedsDisplayInRect() through to the underlying layer 
which I’d have expected. I assume it only calls those that if the layer is a 
normal UIView layer and not a custom one. 

I think as long as that’s the extent of its meddling with ‘its layer’, just 
setting a few properties when it starts up and adjusting the bounds for me, I 
can live with it. I’ll try out a few more things on the view to see if there 
are other things I need to be prepared to deal with, just having it manage the 
layer bounds automatically is helpful if that’s about all it does. 


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: UIView underlying rects for drawRect

2015-12-06 Thread Mike Abdullah

> On 6 Dec 2015, at 01:50, Roland King  wrote:
> 
> You thought CGContext had it, I thought CALayer had it, neither of them 
> appear to have it! 
> 
> AFAICT UIView is clearing the entire rectangle before drawing, so that idea 
> doesn’t work either. That was a good way to confirm I was on the wrong road 
> so thanks.

Aha, that is very interesting to know.
> 
> So I implemented the code to capture setNeedsDisplayInRect(), drawRect() etc 
> and ensure only one contiguous rectangle goes to the setNeedsDisplayInRect at 
> a time, if there’s another one it waits until drawRect() finishes and then 
> queues that one up. The results were good until they weren’t and I’m really 
> at a loss to explain some of the oddities I saw. It was never going to be 
> stable enough for real use so that idea got tossed. 
> 
> Current workaround it not to take things off the back, it’s history, I don’t 
> really care, and the code moves the view along anyway so it quickly gets 
> clipped and every few minutes the view is moved to a new chunk of data (it’s 
> like a horizontal scroll view where only 1.5 screens wide of data is shown at 
> a time which are incrementally drawn and then moved to a new chunk every few 
> minutes with one single redraw). 
> 
> I think a better plan for this whole thing is to use a CALayer with a 
> persistent bitmap for the graph I’m drawing. 
> 
> Currently I’m seeing a new point come in, working out what that is in view 
> coordinates, calling setNeedsDisplayinRect() on that, then in drawRect I’m 
> converting back to time coordinates, padding out each side so I definitely 
> redraw the whole area cleared including the fuzzy edges of lines a point or 
> two over on the display, then drawing. This is probably nowhere near as 
> efficient as possible. 
> 
> If I use a CALayer with a bitmap I can put a point on the bitmap 
> asynchronously as soon as it comes in, one point, or one tiny line segment 
> from the previous point, I can do my own clearing when they expire and then 
> all I have to do is arrange the bitmap to be blitted onto the CALayer’s 
> content on a regular basis for update and sort out some full redraw stuff on 
> bounds change stuff. 
> 
> What’s the right way to synchronise the update of the content property of a 
> CALayer? I could do it every time I add a point, but that sounds a bit 
> unnecessary. Is this where I use CADisplayLink? Is there a recommended format 
> for the bitmap which eases the work the CPU/GPU has to do to transfer it to 
> and from the layer? 8 bit with alpha is all I really need for the plot but if 
> that’s going to trigger a huge conversion every time it’s run through 
> CGBitmapContextCreateImage() and stuffed on the layer I’ll use something 
> else. 

CALayer has a mechanism built in for the sort of thing you want to do. Read up 
on -[CALayer display]. You should be able to override that, or implement the 
corresponding delegate method in your UIView and perform management of your 
custom bitmap there. I myself do this in one app to share one bitmap between 
multiple layers for example.

The other thing worth investigating perhaps is whether CATiledLayer would 
better suit your drawing needs, or if you could split your custom view up into 
a series of sub-views, so you only need invalidate slices of one or two of them.

Mike.
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: UIView underlying rects for drawRect

2015-12-05 Thread Mike Abdullah
I thought CGContext had API to tell you the rects being drawn, but can’t see 
that now, so I think I imagined it!

I’d say your next port of call is to ascertain whether the system is smart 
enough to be only drawing the required area or not. There are debugging tools 
to show you the portions of the screen being updated — does that suggest the 
entire view is being redrawn, or just the ends?

Mike.

> On 5 Dec 2015, at 03:02, Roland King  wrote:
> 
> NSView has a method getRectsBeingDrawn:count: which gives you the actual 
> rects being drawn in a drawRect: call. Is there something equivalent for a 
> UIView? Does UIView even do as I believe NSView does and only invalidate just 
> the areas passed to setNeedsDisplayInRect:, meaning those are the only areas 
> you actually need to redraw, or does it blow away the entire containing 
> rectangle so you must repaint the entire area?  
> 
> I have a time-series view which only invalidates a tiny sliver of view which 
> changed and only draws that in drawRect:. However when the series gets long 
> enough it trims the left hand end, so two tiny slivers of view are 
> invalidated, one at each end, drawRect: coalesces them into one rect the 
> entire size of the window and the whole series redraws on every iteration. I 
> spotted this when I left the simulator running for an hour and the fans 
> suddenly started spinning up. 
> 
> I can work around it by overriding setNeedsDisplayInRect: and queuing up 
> non-contiguous updates, releasing them only when drawRect has been called, 
> but it would be nice not to have to. I suspect I’m SOL on this one. 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/mabdullah%40karelia.com
> 
> This email sent to mabdul...@karelia.com


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: UIView underlying rects for drawRect

2015-12-05 Thread Roland King
You thought CGContext had it, I thought CALayer had it, neither of them appear 
to have it! 

AFAICT UIView is clearing the entire rectangle before drawing, so that idea 
doesn’t work either. That was a good way to confirm I was on the wrong road so 
thanks. 

So I implemented the code to capture setNeedsDisplayInRect(), drawRect() etc 
and ensure only one contiguous rectangle goes to the setNeedsDisplayInRect at a 
time, if there’s another one it waits until drawRect() finishes and then queues 
that one up. The results were good until they weren’t and I’m really at a loss 
to explain some of the oddities I saw. It was never going to be stable enough 
for real use so that idea got tossed. 

Current workaround it not to take things off the back, it’s history, I don’t 
really care, and the code moves the view along anyway so it quickly gets 
clipped and every few minutes the view is moved to a new chunk of data (it’s 
like a horizontal scroll view where only 1.5 screens wide of data is shown at a 
time which are incrementally drawn and then moved to a new chunk every few 
minutes with one single redraw). 

I think a better plan for this whole thing is to use a CALayer with a 
persistent bitmap for the graph I’m drawing. 

Currently I’m seeing a new point come in, working out what that is in view 
coordinates, calling setNeedsDisplayinRect() on that, then in drawRect I’m 
converting back to time coordinates, padding out each side so I definitely 
redraw the whole area cleared including the fuzzy edges of lines a point or two 
over on the display, then drawing. This is probably nowhere near as efficient 
as possible. 

If I use a CALayer with a bitmap I can put a point on the bitmap asynchronously 
as soon as it comes in, one point, or one tiny line segment from the previous 
point, I can do my own clearing when they expire and then all I have to do is 
arrange the bitmap to be blitted onto the CALayer’s content on a regular basis 
for update and sort out some full redraw stuff on bounds change stuff. 

What’s the right way to synchronise the update of the content property of a 
CALayer? I could do it every time I add a point, but that sounds a bit 
unnecessary. Is this where I use CADisplayLink? Is there a recommended format 
for the bitmap which eases the work the CPU/GPU has to do to transfer it to and 
from the layer? 8 bit with alpha is all I really need for the plot but if 
that’s going to trigger a huge conversion every time it’s run through 
CGBitmapContextCreateImage() and stuffed on the layer I’ll use something else. 

Sigh .. I feel a few hours of pain coming up. 



> On 5 Dec 2015, at 18:59, Mike Abdullah  wrote:
> 
> I thought CGContext had API to tell you the rects being drawn, but can’t see 
> that now, so I think I imagined it!
> 
> I’d say your next port of call is to ascertain whether the system is smart 
> enough to be only drawing the required area or not. There are debugging tools 
> to show you the portions of the screen being updated — does that suggest the 
> entire view is being redrawn, or just the ends?
> 
> Mike.
> 
>> On 5 Dec 2015, at 03:02, Roland King  wrote:
>> 
>> NSView has a method getRectsBeingDrawn:count: which gives you the actual 
>> rects being drawn in a drawRect: call. Is there something equivalent for a 
>> UIView? Does UIView even do as I believe NSView does and only invalidate 
>> just the areas passed to setNeedsDisplayInRect:, meaning those are the only 
>> areas you actually need to redraw, or does it blow away the entire 
>> containing rectangle so you must repaint the entire area?  
>> 
>> I have a time-series view which only invalidates a tiny sliver of view which 
>> changed and only draws that in drawRect:. However when the series gets long 
>> enough it trims the left hand end, so two tiny slivers of view are 
>> invalidated, one at each end, drawRect: coalesces them into one rect the 
>> entire size of the window and the whole series redraws on every iteration. I 
>> spotted this when I left the simulator running for an hour and the fans 
>> suddenly started spinning up. 
>> 
>> I can work around it by overriding setNeedsDisplayInRect: and queuing up 
>> non-contiguous updates, releasing them only when drawRect has been called, 
>> but it would be nice not to have to. I suspect I’m SOL on this one. 
>> ___
>> 
>> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
>> 
>> Please do not post admin requests or moderator comments to the list.
>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>> 
>> Help/Unsubscribe/Update your Subscription:
>> https://lists.apple.com/mailman/options/cocoa-dev/mabdullah%40karelia.com
>> 
>> This email sent to mabdul...@karelia.com
> 


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at