msgStore не был объявлен в этой области (XCode) - PullRequest
0 голосов
/ 03 декабря 2009

Я реализую процедуры обратного вызова для внешней статической библиотеки C ++, которая будет использоваться в проекте Objective-C. Теперь у меня проблемы с перемещением данных между обратным вызовом и обычными процедурами. Как вы можете видеть ниже, мой «msgStore» определен как часть класса MyMessage и может использоваться в подпрограммах класса, таких как init (). Однако попытка сделать то же самое из подпрограммы обратного вызова, которая НЕ является частью класса MyMessage , завершается неудачей.

@interface MyMessage : NSObject {
    NSMutableArray *msgStore;
}
@property (nonatomic, retain) IBOutlet NSMutableArray *msgStore;

// Callback functions declarations
void aCBack (const std::string text);

@implementation MyMessage    
@synthesize msgStore;

- (id)init
{
    if ((self = [super init])) { }

    if (msgStore == nil) {
        msgStore = [NSMutableArray arrayWithCapacity:100];        
    }
    return self;
}

void aCBack (const std::string text)
{
    NSString *msg = [[NSString alloc] initWithCString:(const char *)text.c_str() encoding:NSUTF8StringEncoding];
    [msgStore insertObject:msg atIndex:0];
}

Последняя строка кода выдает сообщение об ошибке 'msgStore' не было объявлено в этой области . Я предполагаю, что это потому, что aCBack - простая функция C и, следовательно, не имеет автоматического указателя "self"?

Есть идеи, как сохранить данные, полученные в обратном вызове, для использования внутри класса Obj-C?

Ответы [ 3 ]

1 голос
/ 03 декабря 2009

Вы не можете вызвать msgStore из функции, потому что это не входит в область действия функции.

В функции есть несколько способов добраться до нее.

Один из них - использовать одноэлементный класс. Если вы планируете использовать только одно хранилище сообщений, вы можете сделать этот класс одиночным. Это означает, что вы можете получить экземпляр объекта этого класса, вызвав метод класса, что вы можете сделать из любой области видимости. См. Также: Как должен выглядеть мой синглтон Objective-C?

MyMessage * myMsg = [MyMessage sharedMessage]; // this will get you a pointer to the shared instance

Другой способ, если функция обратного вызова позволяет, вы также можете передать его в качестве аргумента void * data, а затем привести его к MyMessage в функции. Смотрите также ответ Алекса Дима.

PS. Вы создаете массив с помощью [NSArray arrayWithCapacity:], который вы, возможно, захотите сделать [[NSArray arrayWithCapacity:] retain] или просто [[NSArray alloc] initWithCapacity:], чтобы объект не исчезал при следующем раунде автоматического освобождения.

0 голосов
/ 04 декабря 2009

Давайте проясним: Синглтон - это ответ (хотя бы один хороший выбор). Однако крайний срок висит у меня на шее, и я просто должен получить что-то более или менее работающее сегодня. Вот что я использую, здесь и сейчас. Обратите внимание, это не «синглтон» :

@interface MyMessage : NSObject {
    NSMutableArray *msgStore;
}
@property (nonatomic, retain) NSMutableArray *msgStore;
- (void)myStoreMessage: (NSString *) msg;
@end

// Callback C/C++ function declarations
void aCBack (const std::string text);
MyMessage *myObserver = nil;

void aCBack (const std::string text)
{
    NSString *msg = [[NSString alloc] initWithCString:(const char *)text.c_str() encoding:NSUTF8StringEncoding];
    [myObserver myStoreMessage:[NSString stringWithString:msg]];
    [msg release];
    // TODO: fix memory leak
}

@implementation MyMessage    
@synthesize msgStore;

- (id)init
{
    if ((self = [super init])) { }

    if (msgStore == nil) {
        msgStore = [[NSMutableArray arrayWithCapacity:100] retain];
    }
    myObserver = self;
    return self;
}

- (void) myStoreMessage: (NSString *)msg
{
    [self.msgStore insertObject:msg atIndex:0];
}
@end

Что тут скажешь, похоже на работу. Есть утечка памяти с msg, которую я не понял, но в остальном это то, что я буду использовать для демонстрации. Когда наступит время (да, конечно), я реализую правильный синглтон.

0 голосов
/ 03 декабря 2009

Простое решение - передать указатель на объект MyMessage в качестве аргумента функции обратного вызова. Что-то вроде:

void aCBack( MyMessage * message, const std::string text)
{
    NSString *msg = [[NSString alloc] initWithCString:(const char *)text.c_str() encoding:NSUTF8StringEncoding];
    [message.msgStore insertObject:msg atIndex:0];
}
...