Как передать объект для параметра void? - PullRequest
1 голос
/ 19 марта 2012

Я работаю с API MusicPlayer и пытаюсь решить проблему с обратным вызовом пользователя.

У меня есть пользовательские события, которые помещаются в каждое событие нот MIDI. Когда ноты воспроизводятся, эти пользовательские события передают целочисленное значение ноты в функцию обратного вызова пользователя как * inEventData:

void noteUserCallback (void *inClientData, MusicSequence inSequence, MusicTrack inTrack, MusicTimeStamp inEventTime, const MusicEventUserData *inEventData, MusicTimeStamp inStartSliceBeat, MusicTimeStamp inEndSliceBeat)
{
    UserEvent* event = (UserEvent *)inEventData;
    UInt32 size = event->length;
    UInt32 note = event->playedNote;
    UInt32 timestamp = event->tStamp;
    NSLog(@"Size: %lu Note: %lu, Timestamp: %lu", size, note, timestamp);

    switch (note) {
        case 60:
            [whiteKey60 setImage:highlightA];
            break;

        default:
            break;
    }
}

На основании этих заметок я хотел бы внести изменения в пользовательский интерфейс. А именно, у меня есть несколько UIImageViews, которые я хотел бы иметь возможность обновлять различными изображениями в зависимости от значения примечания (см. Выше в выражении switch).

Функция обратного вызова пользователя связана с такой последовательностью:

MusicSequenceSetUserCallback(sequence, noteUserCallback, NULL);

Третий параметр вышеуказанной функции связан с параметром void * inClientData пользовательской функции обратного вызова.

Моя проблема в том, что когда я пытаюсь получить доступ к IBOutlets моего представления из функции обратного вызова пользователя, я не могу. Чтобы это исправить, я попытался передать контроллер представления в функцию MusicSequenceSetUserCallback следующим образом:

MusicSequenceSetUserCallback(sequence, noteUserCallback, self);

Проблема, с которой я столкнулся, заключается в том, что этот параметр inClientData имеет тип void , и я не могу передать объект ViewController *. Я попытался просто создать мост, когда я установил функцию обратного вызова, а затем снова подключился обратно в пользовательской функции обратного вызова, но, похоже, он не работал.

Если у кого-нибудь есть мысли о том, как мне это сделать. Даже если это совершенно другие методы, я был бы очень признателен.

Спасибо.

EDIT

Я попробовал следующее:

MusicSequenceSetUserCallback(sequence, noteUserCallback, (__bridge_retained void *)self);

и

void noteUserCallback (void *inClientData, MusicSequence inSequence, MusicTrack inTrack, MusicTimeStamp inEventTime, const MusicEventUserData *inEventData, MusicTimeStamp inStartSliceBeat, MusicTimeStamp inEndSliceBeat)
{   
    PracticeViewController* pvc = (__bridge_transfer PracticeViewController *)inClientData;

    [pvc.whiteKey21 setImage:pvc.highlightA];

    UserEvent* event = (UserEvent *)inEventData;
    UInt32 size = event->length;
    UInt32 note = event->playedNote;
    UInt32 timestamp = event->tStamp;
    NSLog(@"Size: %lu Note: %lu, Timestamp: %lu", size, note, timestamp);

    switch (note) {
        case 60:
            break;

        default:
            break;
    }
}

К сожалению, это дает мне эту ошибку: Поток 13 AURemoteIO :: IOThread: EXC_BAD_ACCESS (код = 2, адрес = 0x10)

EDIT

Изменение обоих мостов на __bridge заставляет ошибку замолчать, но она все еще не работает должным образом; Призыв к изменению изображения в whiteKey60 не работает. Это не проблема с соединением UIImageView, потому что выполнение того же в viewDidLoad работает нормально.

Что мне кажется в любом случае происходит, это то, что self не делает это с функцией или, возможно, разрывает соединение, когда оно проходит?

1 Ответ

2 голосов
/ 19 марта 2012

Посмотрите еще раз на объявление MusicSequenceSetUserCallback:

OSStatus MusicSequenceSetUserCallback (
    MusicSequence              inSequence,
    MusicSequenceUserCallback  inCallback,
    void                       *inClientData
);
Тип

inClientData не void - это не имеет смысла, переменные в C никогда не могут иметь тип void. Скорее, это void * - грубо говоря, указатель на что-то неуказанное.

Вам нужно привести переменную к void * на входе и к void * на выходе. Если предположить, что self является MyClass *, то:

MusicSequenceSetUserCallback(sequence, noteUserCallback, (void *)self);

и в обратном вызове:

void noteUserCallback (void *inClientData, MusicSequence inSequence, MusicTrack inTrack, MusicTimeStamp inEventTime, const MusicEventUserData *inEventData, MusicTimeStamp inStartSliceBeat, MusicTimeStamp inEndSliceBeat)
{
    MyClass* self = (MyClass *)inClientData;
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...