Как определить, есть ли у UIView делегат, соответствующий протоколу

Я написал собственный класс, который в значительной степени зависит от перетаскивания/позиционирования касания за пределами его собственных границ представления. Существует связанный протокол, определенный с помощью различных соответствующих методов. Примером того, что будет использовать этот протокол, может быть представление, которое позволяет помещать в него вещи из моего пользовательского класса.

Проблема, с которой я сталкиваюсь, заключается в том, чтобы выяснить, когда прикосновение завершено (объект «отброшен»), есть ли объект, который заботится ниже этой позиции. (Вместо «заботится» читать «соответствует протоколу»!).

Если это представление соответствует моему протоколу, это легко, я могу найти его с помощью - (CALayer *)hitTest:(CGPoint)thePoint или чего-то в этом роде и запросить с помощью conformsToProtocol:@protocol(xx).

Но если это представление, которое является подпредставлением UIViewController (например), представление не соответствует протоколу, даже если UIViewController (как его делегат) соответствует. Если представление действительно хочет получать уведомления, мне нужно выяснить, кто его делегат, чтобы отправить сообщение.

Итак, по сути, как мне пройти вверх по иерархии представлений от самого нижнего UIView, спрашивая, соответствует ли каждое представление моему протоколу; а если нет, есть ли у него делегат, и соответствует ли он ..?

Или есть более простой способ, о котором я не подумал?

Большое спасибо..


Решено

Благодаря moshy у меня есть решение:

- (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;
}

Это либо возвращает представление, либо nil, если ничего не соответствует.

Еще раз спасибо..


person DefenestrationDay    schedule 08.02.2010    source источник
comment
Будьте осторожны, если единственными объектами, реализующими протокол, будут UIViews, тогда это будет работать нормально, но если нет, то вы можете в конечном итоге попытаться преобразовать UIViewController в UIView. Вы можете сделать так, чтобы метод вместо этого возвращал (id ‹Protocol›).   -  person jamesmoschou    schedule 09.02.2010


Ответы (1)


Что ж, когда у вас будет самое низкое представление, вы можете подняться по цепочке респондентов, используя - (UIResponder *)nextResponder.

Из документов:

Класс UIResponder не сохраняет и не устанавливает следующего ответчика автоматически, вместо этого по умолчанию возвращается nil. Подклассы должны переопределить этот метод, чтобы установить следующего ответчика. UIView реализует этот метод, возвращая управляющий им объект UIViewController (если он есть) или его суперпредставление (если нет); UIViewController реализует метод, возвращая супервизор своего представления; UIWindow возвращает объект приложения, а UIApplication возвращает nil.

person jamesmoschou    schedule 08.02.2010