Это может быть так же просто, как импортировать заголовки времени выполнения Objective C:
#import <objc/runtime.h>
Тогда компилятор знает, что такое Method
, и вы сможете успешно разыменовать его.
(void(*)(id,SEL,id,id,id))(m->method_imp)
делает m->method_imp
указателем на (пустую) функцию с аргументами типа id,SEL,id,id,id
.Каждый метод Objective-C на самом деле является функцией C, причем первый аргумент является указателем на объект (доступ к которому можно получить с помощью self
), а второй - на селектор (доступный с помощью _cmd
) после обычногопараметры метода.
Таким образом, компилятор теперь утверждает, что у вас есть эта функция с парой аргументов, поэтому вы можете вызывать эту функцию, используя нормальные скобки.Первый аргумент, представляющий объект, второй селектор, а затем все остальные.
Чтобы узнать больше об этом, пожалуйста, найдите указатели на функции и узнайте, как работает среда выполнения Objective-C.
По сути, вы могли бы также использовать следующий код:
objc_msgSend(owner, m->method_name, keyPath, object, change);
Но тогда не было бы необходимости получать метод экземпляра.Теперь, единственное, что вам нужно от метода - это селектор, который у вас уже был.Это означает, что вы могли бы использовать SEL
непосредственно в качестве аргумента контекста, а затем использовать код:
objc_msgSend(owner, (SEL)context, keyPath, object, change);
Что-то о IMP
тогда, которое m->method_imp
определяется как:
В <objc/objc.h>
, IMP
был определен следующим образом:
typedef id (*IMP)(id, SEL, ...);
Немного странный синтаксис, поскольку на самом деле не ясно, какой тип является, а какой -Определение.Ну, только IMP
- это определение в данном случае, остальные id (*)(id, SEL, ...)
- это тип.Чтобы узнать больше об этом, найдите статью об указателях функций.
Итак, это указатель на функцию, которая возвращает объект (id
) и принимает несколько аргументов: значения по умолчанию Objective-C ивероятно, еще немного (обозначается ...
, что означает, что может быть дополнительными аргументами)