On 19 Jan 2009, at 6:49 pm, Kyle Sluder wrote:

Well it sounds like there are a number of issues here:
1) You're throwing exceptions in drawing code.  Even if you catch them
so they don't screw up the draw stack, this will be extremely slow and
have adverse effects on the drawing.


My understanding is that @try is pretty cheap, whereas the @catch is not. Since these exceptions are very rare, the @catch block is not being called routinely, so I'm hoping that it won't impact performance (which is currently swamped by Core Graphics rendering times anyway).

2) You've gotten yourself into a situation in which you're trying to
meaningfully recover from an exception but you have to do it from a
place with outside of the exception's local context.  This is why
Cocoa doesn't use exceptions for general circumstance; they're
notoriously hard to gracefully recover from.

Well, if it means I have to try/catch at every point that I save/ restore the graphics context, so be it, that's what I'll have to do. But I was hoping I could catch it at some top level and "put things right" without this approach being necessary.

Cocoa exceptions are not supposed to be reached in shipped code (which
I'm sure you are aware).  It also sounds like the view state is a
critical component of your app's model.  This sounds like a Very Bad
Idea(TM).

On further investigation, it seems that the majority of the "bad state" is caused by the clipping path being set progressively smaller as the drawing stack goes deeper. As you can probably visualise, that isn't unusual. It means though that if an exception occurs the clipping path may be very small when drawRect: returns. On the face of it I can't see why that should matter - (the clipping path should be mine to do with much as I please with drawRect: as long as I always use addClip rather than setClip), in practice this screws up my scrollbars and rulers in the enclosing NSScrollView. That in turn must be because the scrollview is assuming that the contained view's drawRect: will balance all save/restores of the graphics state.


If it's possible to recover from the exception, have you considered
just fixing the situation, obliterating the graphics context, and
redrawing the view?  Perhaps calling -[NSView renewGState] will make
your view usable again.

I hadn't tried renewGState but I have now and it doesn't help. Since the gState is always renewed when the view is focused prior to drawing, that doesn't surprise me. The effects of the unbalanced context stack are felt when exiting drawRect:, not entering it.

What does appear to help a lot is saving the current context at the top of the drawing stack and putting it back explicitly at the end (as per my previously posted code snippet). If the save/restores are balanced, effectively this is a no-op, as I'm putting back the same context that I saved. If an exception occurred, the save/restores are unbalanced, and this code forces it to balance - thus, the NSScrollView is no longer badly screwed up and things can progress almost normally.

My question is, is this in any way legal?

In other words, the call stack looks like this:


@try
{
        save graphics state
                save graphics state
                        save graphics state
                                save graphics state
                                        // normally draw stuff, but may throw 
an exception
                                restore graphics state
                        restore graphics state
                restore graphics state
        restore graphics state
}
@catch
{
// if there was an exception, the context stack is unbalanced - how to rebalance it in a legal way before exiting?
}



--Graham


_______________________________________________

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

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

Reply via email to