Я сейчас делаю аналогичную вещь для приложения OpenGL, и, поскольку это полезный вопрос (и так долго без ответа), я хочу перевести свое решение. Обратите внимание, что, вероятно, меньше усилий использовать NSArray ... но если вам нужно отточить производительность и / или использовать базовые типы C (или GL или аналогичные необъектные), это должно помочь. Кроме того, прости меня, если я делаю что-то, что не работает в OSX, так как мой код на самом деле для iPhone ... Я уверен, что хотя бы концепции одинаковы. Вот схема шагов:
- Объявите вашу переменную как указатель
- Защитите его от прямого доступа с помощью @ private
- Объявите свойство также как указатель, который будет указывать на любой массив, который мы передаем установщику
- Напишите или синтезируйте метод установки и получения. Мое использование @synthesize, казалось, запутало вещи и привело к утечке памяти, поэтому я пойду по пути самописи.
- (я думаю, отсутствующая ссылка из некоторых предыдущих постов) Поскольку вы возвращаете массив C, выделите память с помощью malloc. Метод init, вероятно, является хорошим местом для этого, и вы можете использовать dealloc или другое место для вызова free (myBuffers), так как ваша переменная имеет достаточно широкий охват.
Я не знаю, что @synthesize будет обрабатывать переменные malloc для вас, но кто-то еще может иметь опыт работы с этим, которого мне не хватает. Поэтому я просто пишу сеттер и геттер. Но обратите внимание, что мы все еще получаем точечный синтаксис и ванильный вид @property в интерфейсе.
Вот код:
В PlayerState.h:
@interface PlayerState : NSObject {
AudioStreamBasicDescription dataFormat;
AudioQueueRef queue;
@private
AudioQueueBufferRef *myBuffers;
// [...]
@property(assign) AudioStreamBasicDescription dataFormat;
@property(assign) AudioQueueRef queue;
@property(assign) AudioQueueBufferRef *myBuffers;
Это дает вам указатель и свойство, последнее из которых эквивалентно методам доступа к памяти, указанной указателем. Мы напишем свои собственные методы доступа и выделим память для указателя и дадим ему что-то, на что можно указать.
Сейчас в PlayerState.m:
-(id)init
{
if (self = [super init]) {
myBuffers = (AudioQueueBufferRef*)malloc(sizeof(AudioQueueBufferRef) * 3);
/* memory is allocated. Free it elsewhere. Note that "Leaks" will
probably falsely flag this, but you can test it in Object Allocations
and see that it is clearly released. */
}
return self;
}
// return an array of structs
-(AudioQueueBufferRef*)myBuffers
{
// you can check for values, etc here, but basically it all comes down to:
return myBuffers;
}
// the setter; there are several ways to write it, depending on what your objective
-(void)setMyBuffers:(AudioQueueBufferRef*)abc
{
int i = 3;
while (i > 0) {
i--;
myBuffers[i] = abc[i];
}
//another possible implementation, not tested
//free(myBuffers);
//myBuffers = NULL;
//myBuffers = xyz;
}
// if you want to set individual attributes, you can have another method like:
-(void)setMyBuffersA:(AudioQueueBufferRef)a B:(AudioQueueBufferRef)b C:(AudioQueueBufferRef)c
{
myBuffers[0] = a;
myBuffers[1] = b;
myBuffers[2] = c;
}
Теперь вы можете вызывать их из другого класса, например так:
-(void)methodOfOtherClass
{
PlayerState * playerState = [[PlayerState alloc] init];
AudioQueueBufferRef abc[3] = //something
[playerState setMyBuffers:(AudioQueueBufferRef*)abc];
DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2])
abc[1] = 6.22; // reassigning one of the values in our local variable
playerState.myBuffers = (GLfloat*)abc; //call the setter again, with dot syntax this time if you like
DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2])
[playerState setMyBuffersA:yourStructA B:yourStructB C:yourStructC];
DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2])
}
Это нормально для меня, используя iPhone OS и мои (по общему признанию немного отличающиеся) типы openGL. Тем не менее, я думаю, что это будет работать и для вас. Возможно, вам придется что-то скорректировать, или я ввел небольшую опечатку при копировании и вставке поверх моего исходного кода. Кроме того, если вам нравится регистрировать вещи во время кодирования, как я, возможно, было бы более полезно зарегистрировать некоторый элемент структуры буфера, чтобы увидеть, что там есть то, что должно быть там.
Также, если вы привыкли печатать объекты во время кодирования с помощью оболочки NSLog, то есть: DLog(@"array is %@", myNSarray)
, вы получите EXC_BAD_ACCESS
, пытающийся сделать то же самое с массивом C. Массив C не является объектом Obj-C, так что имейте это в виду и держите его за руку немного больше, чем объект Objective-C;)