views:

285

answers:

1

Howdy all,

I have written a custom class that depends significantly on touch dragging/positioning, outside of it's own view boundaries. There is an associated protocol defined with various relevant methods. An example of something that would use this protocol would be a view that allows things to be dropped into it from my custom class.

The problem I have is in figuring out when a touch is ended (the object is 'dropped'), whether or not there is an object that cares below that position. (For 'cares', read 'conforms to the protocol'!).

If it's a view that conforms to my protocol, it's easy, I can find it with - (CALayer *)hitTest:(CGPoint)thePoint or something along those lines and query with a conformsToProtocol:@protocol(xx).

But if it is a view which is a subview of a UIViewController (for example), the view does not conform to the protocol, even though the UIViewController (as it's delegate) does. If the view really does want to be notified, I need to be able to figure out who it's delegate is, to message.

So, essentially, how do I traverse up the view hierarchy from the lowest UIView, asking if each view conforms to my protocol; and if it doesn't, does it have a delegate, and does that conform..?

Or is there a much easier way I haven't thought of?

Thanks very much..


Solved

Thanks to moshy, I've got a solution:

- (UIView *)viewThatConformsToProtocol:(Protocol *)protocol AtPointInWindow:(CGPoint)point {
   UIView *lowestUIView = [[(AppDelegate).navigationController view] hitTest:point withEvent:nil];
   UIResponder *respondsToProtocol = lowestUIView;
   while ((respondsToProtocol != nil) && (![respondsToProtocol conformsToProtocol:protocol])) {
      respondsToProtocol = [respondsToProtocol nextResponder]; // else try the next responder up the chain
   };
   return (UIView *)respondsToProtocol;
}

This either returns the view, or nil if nothing conforms.

Thanks again..

A: 

Well, once you have the lowest view, you could walk up the responder chain using - (UIResponder *)nextResponder.

From the docs:

The UIResponder class does not store or set the next responder automatically, instead returning nil by default. Subclasses must override this method to set the next responder. UIView implements this method by returning the UIViewController object that manages it (if it has one) or its superview (if it doesn’t); UIViewController implements the method by returning its view’s superview; UIWindow returns the application object, and UIApplication returns nil.

moshy