Re: Changing order of views dynamically
Re: Changing order of views dynamically
- Subject: Re: Changing order of views dynamically
- From: Michael Watson <email@hidden>
- Date: Tue, 20 Mar 2007 06:24:13 -0400
Did you read the link Andreas gave you? Apple says specifically that
view overlapping should not be done. It's a performance concern /and/
an implementation concern:
1. You don't know what Apple's going to do with Cocoa beneath the
hood in system updates. Something may (and likely will) change, and
that could affect your application adversely. Don't say, "I can patch
then," because that means you wrote it wrong to begin with. Your
users now have to update because you didn't pay attention in class.
2. Because Apple says not to do it, they leave the behaviour
technically undefined. You can't predict what will happen, and risk
introducing bugs into your application.
QUESTION: Why does this stuff matter, you ask? Why should you give a
damn? I mean, "it works" for you, right?
ANSWER: When it doesn't work, or performance is hindered, it makes
the entire platform look bad. When something goes wrong, it's your
users who pay for it, not you.
Do. Not. Overlap. Cocoa. Views.
--
m-s
On 20 Mar, 2007, at 04:40, Sergey Shapovalov wrote:
All,
it looks like I've tracked down the problem myself and found a
workaround for what I wanted to do originally. From the first
glance it seems to work. However, from your posts and references to
Apple guidelines, I realize that this is a kind of hack, not a
legal solution. So I believe I can face problems with it in the
future. I'd appreciate if anyone warns me concerning what exactly
kind of trouble I should expect...
Now: how it works. Every NSView has an array of subviews available
through [NSView subviews]. When I add a subview via [NSView
addSubview:], it goes to the end of the array. When I add a subview
via [NSView addSubview:positioned:relativeTo:], it is inserted
before or after the relative subview into this array.
When the parent view draws itself, it also re-draws its subviews in
a loop. It calls drawRect for the subviews in the same order as the
subviews go in the array. That's why if the subviews (partially)
overlap, the ones with smaller indices in the array appear below
the ones with bigger indices.
Of course this can be spoiled if a subview decides to re-draw
itself on its own, not due to a command from the parent. Then it
may become drawn above other sibling subviews. But it doesn't seem
to ever happen in my particular case.
So, now the solution is evident. To provide proper positioning of
some subviews over others, I need proper sorting of the subviews
array. And yes - there is a function to do this:
[NSView sortSubviewsUsingFunction:context:].
I've already tried it, and as I already said, it seems to work, at
least from the first glance.
However, I suspect that I might have missed something (it's too
good to be true). Can anyone explain to me what is wrong with my
approach?
Best regards,
Sergey.
On Mar 20, 2007, at 10:16 AM, Sergey Shapovalov wrote:
Andreas,
thank you very much for your reply and for the link.
2. I don't need to swap the views. I need to swap the *order* of
the views.
Why? They should not overlap anyway. Please read:
http://developer.apple.com/documentation/Cocoa/Conceptual/
CocoaViewsGuide/WorkingWithAViewHierarchy/chapter_4_section_1.html
Especially:
"Note: For performance reasons, Cocoa does not enforce clipping
among
sibling views or guarantee correct invalidation and drawing behavior
when sibling views overlap. If you want a view to be drawn in front
of another view, you should make the front view a subview (or
descendant) of the rear view."
Yes, I get the point and I admit that what I was going to do has
been illegal. But in order to provide a complete view of the issue
to me, could anyone please explain the following 3 things?
1. What is [NSView addSubview:positioned:relativeTo:] intended for
if relative positioning of overlapping subviews is not guaranteed
to work anyway? If "correct invalidation and drawing behavior when
sibling views overlap" is not guaranteed, is it just a misleading
API which will never work?
When I found this function, I thought that it should work for the
following case. I have a view V and a subview SV1, and at run-
time, I want to add another subview SV2 to the view V, and I want
SV2 to be drawn above SV1. So I create SV2 and call
[V addSubview: SV2 positioned: NSWindowAbove relativeTo: SV1];
Is this illegal? If so, what is the legal use of this method?
2. When I build a NIB resource in Interface Builder, I can choose
several sibling subviews in a parent view, and for each of them
say "Layout > Bring To Front" or "Layout > Send To Back". Is this
also illegal in case these sibling subviews overlap? I mean, is
there no guarantee that what was brought to front will be drawn
above what was sent to back?
3. In my case, the relative positioning of overlapping sibling
subviews (via calling addSubview:positioned:relativeTo:) did work
so far. I mean, in my "time-line control" analog the subviews that
were added above are actually drawn above the subviews added
below. Is it just a case of good luck? Can this stop working with
a next major Mac OS X release?
Again: I'm not arguing, and I'm not defending my original
approach. A admit that I was wrong. Thank you all for pointing
this out to me. But now I just want to understand how things work
in Cocoa...
Best regards,
Sergey.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden