Прикосновение к крючку начинается в классе UIView [Swizzling] с Delphi XE5
Я пытаюсь поймать все сенсорные события во всем мире. Для этого я знаю, что могу подключить процедуры сенсорного события внутри класса UIView. У меня есть код, который компилируется. Моя реализация крючка
procedure touchesBeganDetour(self: id; _cmd: SEL; touches: NSSet; withEvent: UIEvent); cdecl;
begin
Sleep(1);
end;
И тогда я попытался подключить его двумя разными способами. Первый:
constructor TTouchEventListener_IOS.Create;
var
FM1, FM2: Pointer
ViewClass: Pointer;
begin
inherited;
ViewClass := objc_getClass('UIView');
class_addMethod(ViewClass, sel_getUid('touchesBeganDetour:'), @touchesBeganDetour, 'v@:@@');
FM1 := class_getInstanceMethod(ViewClass, sel_getUid('touchesBegan:withEvent:'));
FM2 := class_getInstanceMethod(ViewClass, sel_getUid('touchesBeganDetour:'));
method_exchangeImplementations(FM1, FM2);
end;
Это кажется стандартным подходом. И второй:
constructor TTouchEventListener_IOS.Create;
var
FM1
ViewClass: Pointer;
begin
inherited;
ViewClass := objc_getClass('UIView');
FM1 := class_getInstanceMethod(ViewClass, sel_getUid('touchesBegan:withEvent:'));
method_setImplementation(FM1, @touchesBeganDetour);
end;
Это также должно работать, насколько я понимаю. Я получаю экземпляр "touchesBegan: withEvent", и весь код выполняется без ошибок. Но когда я прикасаюсь к экрану симулятора, код падает внутри "DispatchToImportSuper" в блоке "Macapi.ObjectiveC.pas". Я явно делаю что-то не так, но понятия не имею, что. Если это сработает, это позволит прослушивать сенсорные события без изменения исходного кода Delphi.
У кого-нибудь есть идеи?
1 ответ
Чтобы снова ответить на мой собственный вопрос. Проблема была в декларации процедуры объезда. Кажется, вы не можете указать исходные параметры, но вы должны использовать указатели вместо интерфейсов. Вероятно, это связано с различиями в ObjectiveC и Паскале объекта. Позже вы "обернетесь" и таким образом приведете указатели к правильным интерфейсам.
procedure touchesBeganDetour(self: id; _cmd: SEL; touches: Pointer; withEvent: Pointer); cdecl;
begin
DoNotifyTouchEvent(TNSSet.Wrap(touches), TUIEvent.Wrap(withEvent), teDown);
end;