Re: Changing Subview Order Prevents Dragging

2013-05-13 Thread Andy Lee
On May 14, 2013, at 1:16 AM, Andy Lee  wrote:
> I fiddled a bit with it, adding calls that don't take arguments like [self 
> description] and [self self]. There was no dealloc until just before the 
> method exited, after those calls. It *seems* that merely referring to self, 
> whether as receiver or argument, keeps it alive. However, I might just have 
> been lucky.

Or, as was suggested, something else might well have been retaining self.

--Andy



___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Andy Lee
On May 14, 2013, at 12:53 AM, Roland King  wrote:
[...]
>> - (void) mouseDown: (NSEvent*) event
>> {
>>NSView* superView = [self superview];
>>[self removeFromSuperview];
>> //[superView addSubview: self];
>> }
>> 
>> ...then dealloc does in fact get called. But if I uncomment that one line, 
>> which references self, dealloc does not get called. This is good news -- I 
>> would want ARC to work regardless of whether it calls non-ARC code, and vice 
>> versa.
>> 
> 
> well you have several lines in there which reference self, [ self superview ] 
> and [ self removeFromSuperview ].

I was thinking that if calling [self removeFromSuperview] removed the last 
reference to self, dealloc would have been called in both cases. Naturally I 
wouldn't expect self to have been dealloc'ed before that statement.

> The only difference in the last one is that self is used as a parameter to a 
> call to another object and that may possibly be the difference.

I fiddled a bit with it, adding calls that don't take arguments like [self 
description] and [self self]. There was no dealloc until just before the method 
exited, after those calls. It *seems* that merely referring to self, whether as 
receiver or argument, keeps it alive. However, I might just have been lucky.

> And the LLVM documents talk about this, they say that self is not retained 
> during a method call. 
> 
> http://clang.llvm.org/docs/AutomaticReferenceCounting.html#self
> 
> and discuss exactly this risk.

Thanks. Just goes to show it's dangerous to guess too much -- in my case, that 
self is a strong reference -- from too little evidence.

--Andy


___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Quincey Morris
On May 13, 2013, at 21:30 , Andy Lee  wrote:

> I believe ARC keeps it alive by virtue of self being a strong reference.

It isn't, not exactly. According to section 7.3 of the Clang ARC spec:

"The self parameter variable of an Objective-C method is never actually 
retained by the implementation. It is undefined behavior, or at least 
dangerous, to cause an object to be deallocated during a message send to that 
object."

This is the case when the receiver of the method invocation is itself a strong 
reference. If it's actually a __weak reference, it *is* retained for the 
duration of the method execution, because of the rules for retention of __weak 
objects used in expressions.

> I did a quick test and found that if I do
> 
> - (void) mouseDown: (NSEvent*) event
> {
>NSView* superView = [self superview];
>[self removeFromSuperview];
> //[superView addSubview: self];
> }
> 
> ...then dealloc does in fact get called. But if I uncomment that one line, 
> which references self, dealloc does not get called.

I suspect it works because the ARC implementation is "suboptimal", in the sense 
that it's causing self to be autoreleased as a result of being used in a later 
expression. If the implementation ever improved to avoid using autorelease, I'd 
expect it to start crashing in this scenario.

___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Roland King

On 14 May, 2013, at 12:30 PM, Andy Lee  wrote:

> On May 13, 2013, at 11:38 PM, Quincey Morris 
>  wrote:
>> On May 13, 2013, at 19:41 , Graham Cox  wrote:
>> 
>>> When you call -removeFromSuperview, the view is deleted, as there are no 
>>> more references to it. The other methods are not called because the object 
>>> ceases to exist.
>> 
>> I believe your warning is apposite, but is not actually the cause of Tom's 
>> problem. After removing the view, his code adds it back again. If the view 
>> had already been deallocated, you'd expect a pretty big crash pretty soon 
>> (though not necessarily immediately).
>> 
>> My guess is that the removed view is still retained by something,
> 
> I believe ARC keeps it alive by virtue of self being a strong reference. I 
> did a quick test and found that if I do
> 
> - (void) mouseDown: (NSEvent*) event
> {
>NSView* superView = [self superview];
>[self removeFromSuperview];
> //[superView addSubview: self];
> }
> 
> ...then dealloc does in fact get called. But if I uncomment that one line, 
> which references self, dealloc does not get called. This is good news -- I 
> would want ARC to work regardless of whether it calls non-ARC code, and vice 
> versa.
> 

well you have several lines in there which reference self, [ self superview ] 
and [ self removeFromSuperview ]. The only difference in the last one is that 
self is used as a parameter to a call to another object and that may possibly 
be the difference. 

And the LLVM documents talk about this, they say that self is not retained 
during a method call. 

http://clang.llvm.org/docs/AutomaticReferenceCounting.html#self

and discuss exactly this risk. 



___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Thomas Wetmore
Not only does this work, it also does not add duplicates to the subviews array.

Tom

On May 13, 2013, at 11:56 PM, Thomas Wetmore  wrote:

> This works. Thanks for the tip.
> 
> Tom Wetmore
> 
> On May 13, 2013, at 11:38 PM, Quincey Morris 
>  wrote:
> 
>> -- Invoke 'addSubview: self' without first removing self. The NSView 
>> machinery may be clever enough merely to move the view to the end of the 
>> subviews array, without actually removing and re-adding it.
> 


___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Andy Lee
On May 13, 2013, at 11:38 PM, Quincey Morris 
 wrote:
> On May 13, 2013, at 19:41 , Graham Cox  wrote:
> 
>> When you call -removeFromSuperview, the view is deleted, as there are no 
>> more references to it. The other methods are not called because the object 
>> ceases to exist.
> 
> I believe your warning is apposite, but is not actually the cause of Tom's 
> problem. After removing the view, his code adds it back again. If the view 
> had already been deallocated, you'd expect a pretty big crash pretty soon 
> (though not necessarily immediately).
> 
> My guess is that the removed view is still retained by something,

I believe ARC keeps it alive by virtue of self being a strong reference. I did 
a quick test and found that if I do

- (void) mouseDown: (NSEvent*) event
{
NSView* superView = [self superview];
[self removeFromSuperview];
//[superView addSubview: self];
}

...then dealloc does in fact get called. But if I uncomment that one line, 
which references self, dealloc does not get called. This is good news -- I 
would want ARC to work regardless of whether it calls non-ARC code, and vice 
versa.

> but that removing a view from its window causes the mouse-dragging state 
> machine to be reset. If so, immediately re-adding the view isn't going to 
> restore the dragging state.

This sounds very plausible.

> 
> I think the trick is to avoid removing the view from its superview. I'm not 
> sure of the *best* way of doing this, but here are the things I'd try:
> 
> -- Invoke 'addSubview: self' without first removing self.

On May 13, 2013, at 11:56 PM, Thomas Wetmore  wrote:
> This works. Thanks for the tip.

Oh, good. I was going to suggest instead of removing and re-adding self, that 
you remove and re-add all the sibling views that are in front of self so that 
they are behind self, using addSubview:positioned:relativeTo:. That would have 
been very ugly.

--Andy


___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Thomas Wetmore
This works. Thanks for the tip.

Tom Wetmore

On May 13, 2013, at 11:38 PM, Quincey Morris 
 wrote:

> -- Invoke 'addSubview: self' without first removing self. The NSView 
> machinery may be clever enough merely to move the view to the end of the 
> subviews array, without actually removing and re-adding it.


___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Roland King


On 14 May, 2013, at 11:34, Graham Cox  wrote:

> 
> Or just do it manually. It's not incompatible with ARC which after all simply 
> inserts the same calls. To my mind, it's clearer what's going on than relying 
> on all those arcane magic pointer types.
> 
> --Graham
> 
> 

You'd have to disable arc on that file on that case. Explicit retain release in 
an arc enabled source file are syntax errors. 


___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Quincey Morris
On May 13, 2013, at 19:41 , Graham Cox  wrote:

> When you call -removeFromSuperview, the view is deleted, as there are no more 
> references to it. The other methods are not called because the object ceases 
> to exist.

I believe your warning is apposite, but is not actually the cause of Tom's 
problem. After removing the view, his code adds it back again. If the view had 
already been deallocated, you'd expect a pretty big crash pretty soon (though 
not necessarily immediately).

My guess is that the removed view is still retained by something, but that 
removing a view from its window causes the mouse-dragging state machine to be 
reset. If so, immediately re-adding the view isn't going to restore the 
dragging state.

I think the trick is to avoid removing the view from its superview. I'm not 
sure of the *best* way of doing this, but here are the things I'd try:

-- Invoke 'addSubview: self' without first removing self. The NSView machinery 
may be clever enough merely to move the view to the end of the subviews array, 
without actually removing and re-adding it.

-- Create a mutable copy of 'self.superview.subviews', move 'self' to the end 
of the mutable copy, then use 'self.superview setSubviews:' to establish the 
new order. Note that using 'setSubviews:' this way is explicitly called out in 
the NSView documentation as a way of reordering views.

-- Use 'sortSubviewsUsingFunction:context:' with a suitable comparison function 
to move 'self' to the end of the subviews.

Of course, it's still possible that any or all of the above will reset the 
dragging state, but they're certainly worth a try.

P.S. The OP's issue is one reason why using "many small, draggable views" 
probably isn't a good design solution to the problem anyway.

___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Graham Cox

On 14/05/2013, at 1:14 PM, Roland King  wrote:

> That depends on whether the framework which is calling mouseUp:/mouseDown: 
> retains the object on which it's calling it. If the framework is using ARC 
> and a normal strong reference, then it would be retained and that would stop 
> it deallocing, if it's not using ARC then it depends on whether the framework 
> retains the view explicitly, which it probably should since it's trying to 
> use it but I have no idea whether it does or not. 

I'm pretty sure it doesn't, at least between the mouseDown and mouseDragged 
phases - it may for repeated calls to mouseDragged. I have run into this exact 
issue in the past.


> Not too hard to test, stick a breakpoint in the dealloc() method and see if 
> it's called from within one of the mouseUp:/mouseDown: methods. 
> 
> If you are losing it, you can assign self to a strong reference at the start 
> of the method which you nil out again after you've done your window shuffle, 
> and that will hang onto it (as long as it doesn't get optimized out).

Or just do it manually. It's not incompatible with ARC which after all simply 
inserts the same calls. To my mind, it's clearer what's going on than relying 
on all those arcane magic pointer types.

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

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


Re: Changing Subview Order Prevents Dragging

2013-05-13 Thread Roland King

On 14 May, 2013, at 10:41 AM, Graham Cox  wrote:

> 
> On 14/05/2013, at 12:27 PM, Thomas Wetmore  wrote:
> 
>> Can anyone suggest why adding the three lines in mouseDown prevents 
>> dragging? Using ARC.
> 
> 
> When you call -removeFromSuperview, the view is deleted, as there are no more 
> references to it. The other methods are not called because the object ceases 
> to exist.
> 
> You need to retain it, remove it, add it to the superview then release it. 
> ARC won't automatically help you out in this case because you're deallocing 
> self, indirectly, which is not a good idea.
> 

That depends on whether the framework which is calling mouseUp:/mouseDown: 
retains the object on which it's calling it. If the framework is using ARC and 
a normal strong reference, then it would be retained and that would stop it 
deallocing, if it's not using ARC then it depends on whether the framework 
retains the view explicitly, which it probably should since it's trying to use 
it but I have no idea whether it does or not. 

Not too hard to test, stick a breakpoint in the dealloc() method and see if 
it's called from within one of the mouseUp:/mouseDown: methods. 

If you are losing it, you can assign self to a strong reference at the start of 
the method which you nil out again after you've done your window shuffle, and 
that will hang onto it (as long as it doesn't get optimized out).


___

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: Changing Subview Order Prevents Dragging

2013-05-13 Thread Graham Cox

On 14/05/2013, at 12:27 PM, Thomas Wetmore  wrote:

> Can anyone suggest why adding the three lines in mouseDown prevents dragging? 
> Using ARC.


When you call -removeFromSuperview, the view is deleted, as there are no more 
references to it. The other methods are not called because the object ceases to 
exist.

You need to retain it, remove it, add it to the superview then release it. ARC 
won't automatically help you out in this case because you're deallocing self, 
indirectly, which is not a good idea.

[self retain];
[self removeFromSuperview];
[superview addSubview:self];
[self release];


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

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


Changing Subview Order Prevents Dragging

2013-05-13 Thread Thomas Wetmore
I've been experimenting with a UI for a program that manages many small, 
draggable views, that can be moved around in the same superview. The following 
mouse events work well for providing the dragging basics. However, when I drag 
a view relative to the other views I also want it to end up on top if there is 
overlap. If I add the three lines of code that are commented out in the 
mouseDown method, the mouseDragged method stops being called, so the views 
won't move. On the other hand, if I add those three lines to the mouseUp 
method, the views move fine, and they transition to the top fine, but only at 
the very end of the drag, which looks strange as the view pops up through all 
the other views that were over it.

Can anyone suggest why adding the three lines in mouseDown prevents dragging? 
Using ARC.

Thanks,

Tom Wetmore


- (void) mouseDown: (NSEvent*) event
{
//NSView* superView = [self superview];
//[self removeFromSuperview];
//[superView addSubview: self];

_startClick = [event locationInWindow];
_startFrame = [self frame];
_dragging = YES;
}

- (void) mouseDragged: (NSEvent*) event
{
if (_dragging) {
NSPoint clickPoint = [event locationInWindow];
NSRect frame = [self frame];
frame.origin.x = _startFrame.origin.x + clickPoint.x - _startClick.x;
frame.origin.y = _startFrame.origin.y + clickPoint.y - _startClick.y;
[self setFrame: frame];
[self setNeedsDisplayInRect: frame];
[self autoscroll: event];
}
}

- (void) mouseUp: (NSEvent*) event
{
_dragging = NO;

//NSView* superView = [self superview];
//[self removeFromSuperview];
//[superView addSubview: self];
}


___

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