【问题标题】:msgStore was not declared in this scope (XCode)msgStore 未在此范围内声明(XCode)
【发布时间】:2009-12-03 10:37:15
【问题描述】:

我正在为要在 Objective-C 项目中使用的外部静态 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' is not declared in this scope。我猜这是因为 aCBack 是一个普通的 C 函数,因此没有自动“自我”指针?

任何想法如何保存在回调中接收到的数据以便在 Obj-C 类中使用?

【问题讨论】:

  • 我可以在回调中做 Obj-C 的东西,所以我能以某种方式创建或请求 MyMessage 对象指针吗?不是创建新对象,而是指向已经存在的对象?好吧,我猜一种解决方案可能是将 msgStore 创建为单例。希望会有更简单的事情......

标签: c++ objective-c scope callback


【解决方案1】:

您不能从函数中调用msgStore,因为它不在函数的范围内。

有几种方法可以在函数中找到它。

一种是使用单例类。如果您打算只使用一个消息存储,那么您可以将该类设为单例。这意味着您可以通过调用类方法来获取该类的对象实例,您可以在任何范围内执行此操作。另见:What should my Objective-C singleton look like?

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

另一种方法是,如果回调函数允许,您也可以将其作为void * data 参数传递,然后在函数中将其转换为MyMessage。另请参阅 Alex Deem 的回答。

PS。您使用[NSArray arrayWithCapacity:] 创建数组,您可能想要创建[[NSArray arrayWithCapacity:] retain] 或只是[[NSArray alloc] initWithCapacity:],因此该对象不会在下一轮自动释放池内务处理中消失。

【讨论】:

  • 感谢这两个提示!单例似乎真的是解决这个问题的方法(在这之间做了一些阅读),特别是对于家政服务!然而,我的 Quick But Dirty 解决方案是另外一回事,没有时间进行适当的单身......更多下文。但你的答案是对的!
【解决方案2】:

简单的解决方案是将指向 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];
}

【讨论】:

  • aCBack 被声明在我无法触及的范围内。我必须将 aCBack 函数指针指向库,以便它可以回调我。因此不能添加 MyMessage 对象作为附加参数。这将使外部库依赖于我的实现,这是不允许的......
  • 您可以使用 void * 并根据需要对其进行类型转换,而不是使用 MyMessage *。如果回调中没有指示回调与哪个对象相关的内容,您真的不知道。想象一下当您有多个 MyMessage 对象同时等待回调的情况。当回调来时,你怎么知道它是针对哪一个的?
  • 必须检查一下,谢谢!顺便说一句,这个例子大大简化了。我有 5 个用于不同目的的回调,但只有一个“对象”来处理它们。此对象将在发生某些事情时发送通知,感兴趣的那些(对象)可以请求更多信息。是的,计划重构,但现在只是让它作为演示工作。
【解决方案3】:

让我们明确一点:单例就是答案(至少是一个不错的选择)。然而最后期限就在我的脖子上,我今天或多或少地得到了一些工作。这就是我现在使用的。请注意这不是“单例”

@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 存在内存泄漏,我还没有弄清楚,否则这就是我将用于演示的内容。之后有时间(是的,当然)我会实现一个合适的单例。

【讨论】:

  • 使用全局变量也可以:-p 又快又脏!这里的内存泄漏是你在MyMessage 中没有dealloc。您应该解除分配 msgStore。此外,由于您使用全局变量,因此最好在您的 dealloc 方法中将 myObserver 设置为 Nil。此外,在 init 方法中,除了 return self 之外的所有内容都应该在 (self = [super init]) 的荣誉之间。
  • 整个文件大约200行,不得不缩短:有dealloc,但添加了myObserver = nil;也感谢初始化修复!内存泄漏实际上与 aCBack 例程中的 msg 相关...回调是从与 MyMessage 对象不同的线程调用的,这可能与它有关。很可能我只需要在回调中定义本地 NSAutoReleasePool。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 2016-08-09
  • 2019-02-17
  • 2021-01-07
  • 2016-10-27
相关资源
最近更新 更多