Одна функция obj-c прекрасно работает в обратном вызове C, другая - нет, когда вызывается точно так же - PullRequest
1 голос
/ 29 мая 2011

У меня есть приложение, которое использует метод обратного вызова C для получения мультитач-информации с трекпада macbook. Вот усеченная версия того, как я передаю эти данные пользователю:

в MT2AppDelegate.h:

#import "MyView.h"
@interface MT2AppDelegate : NSObject <NSApplicationDelegate> {
        IBOutlet NSTextField *L1;
        IBOutlet MyView *MTView;
}
@property (retain, nonatomic) IBOutlet MyView *MTView;
@property (retain, nonatomic) IBOutlet NSTextField *L1;

в MT2AppDelegate.m:

#import "etc. etc."
static MT2AppDelegate *sharedWithCAppDelegateReference;
@implementation MT2AppDelegate
@synthesize L1, MTView;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    sharedWithCAppDelegateReference=self;

    [L1 setStringValue:@"Hello"];//this works
        [MTView drawRect2];//this also works

    MTDeviceRef dev = MTDeviceCreateDefault();
    MTRegisterContactFrameCallback(dev, callback);
    MTDeviceStart(dev, 0);
}


int callback( int example, float etc) {

                [sharedWithCAppDelegateReference->L1 setStringValue:@"hello"];//this works 
                [sharedWithCAppDelegateReference->MTView drawRect2];//this does NOT work
        return 0;
}

Так что по какой-то причине использование функции на одном IBOutlet работает из C просто отлично, в то время как другая ничего не делает. Те же две функции обе работают в target-c. Я также не могу вызвать функцию из делегата приложения внутри C. Например, [sharedWithCAppDelegateReference setPoint]; ничего не делает.

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

В настоящее время у меня есть делегат приложения с функцией обратного вызова внутри него и другой класс («MyView»), который является классом представления в окне моего приложения. Делегат приложения связан с представлением через IBOutlet в конструкторе интерфейса, и я планирую передать ему команды, чтобы обновить местоположение овалов, представляющих пальцы. Но опять же, это не работает для меня.

1 Ответ

1 голос
/ 29 мая 2011

Не использовать ->; совершенно не стандартная атмосфера Obj-C. Кроме того, переменные и свойства экземпляра должны начинаться со строчных букв.

Основная проблема заключается в том, что API обратного вызова не имеет значения указателей контекста. Большинство API обратного вызова определены как:

void fooBackMan(int a, float b, void *context);

Где вы устанавливаете что-то вроде:

extern set_up_callback(void(*callb)(int,float,void*), void*);
set_up_callback(&myCallbackFunc, someObject);

И, когда вызывается обратный вызов, указатель контекста указывает на то, что вы передали в функцию set_up_callback(). Как правило, вы передаете self или какой-либо другой объект в качестве контекста (сначала сохраняемый, конечно), а затем вы можете типизировать и вызывать методы для него, как и любой другой объект.

Ваш обратный вызов не делает этого, и поэтому вам нужна глобальная переменная, и ваше решение в значительной степени соответствует ожидаемому поведению. Сохранить для использования ->. Не делай этого.

Вместо этого я бы определил метод, подобный -handleMTCallbackWithExample:(int)anEx etc:(float)anEtc;, а затем вызвал бы его как одну строку кода в моем callback() func.

...