NSArray如何获得c ++对象的所有权

时间:2014-08-06 09:10:42

标签: c++ ios objective-c objective-c++

据我所知,iOS中的c ++对象是在堆栈内存中分配的。现在我必须将c ++对象添加到NSArray中,但是NSArray不能直接存储c ++对象。

问题是如何在NSArray中存储c ++对象并让NSArray获得c ++对象的所有权,以便我可以随时使用c ++对象。

感谢您的帮助!

========= EDIT ======== 以下是一些代码段:

std::list<ImageTextContent> msgs = body->getMsgs();
std::list<ImageTextContent>::iterator itmsgs0;
for(itmsgs0 = msgs.begin();itmsgs0 != msgs.end();itmsgs0++)
{
   ImageTextContent *tmpmsgs = &(*itmsgs0);
   ImageTextContentWrapper *itc = [[ImageTextContentWrapper alloc] initWithImageTextContent:tmpmsgs];

   [self.dataSource addObject:itc];
}
[self.tableview reloadData];

cellForRow方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ........
    ImageTextContentWrapper *itc = (ImageTextContentWrapper *)[_dataSource objectAtIndex:indextPath.row];
    NSString *title = [NSString stringWithCString:(itc.imageTextContent->getTitle()).c_str() encoding:NSUTF8StringEncoding];
    cell.titleLabel.text = title;
    ........
}

ImageTextContentWrapper类:

@interface ImageTextContentWrapper : NSObject

@property (nonatomic, assign) ImageTextContent *imageTextContent;

- (id)initWithImageTextContent:(ImageTextContent *)imageTextContent;
@end


@implementation ImageTextContentWrapper

- (id)initWithImageTextContent:(ImageTextContent *)imageTextContent
{
    if (self = [super init])
    {
        self.imageTextContent = imageTextContent;
    }

    return self;
}

@end

3 个答案:

答案 0 :(得分:2)

创建一个拥有C ++对象的Objective-C类,并在NSArray中存储此类的对象。

答案 1 :(得分:1)

你有点不合时宜。有两种方法可以创建C ++对象。在堆栈上(通过将其声明为本地非指针变量)或在堆上(例如,使用运算符new或将其声明为ObjC对象中的非指针实例变量)。

如果你实际上在堆栈中有一个,则无法(安全地)从ObjC类引用它。在ObjC中,所有对象都在堆上,因此保留它的每个人都保证即使声明它的函数返回它也会保持不变。发布它的最后一个导致其内存实际上被释放。

你不能用堆栈对象来保证,因为它们必须在它们是局部变量的函数返回时消失。

但是如果您可以使用运算符new创建C ++对象并且代码仍然有效,而不是堆栈对象,那么您可以在 ObjC ++ 文件中创建一个ObjC类(.mm后缀而不是直的.m),并将其放在一个数组中。如果您想了解更多关于ObjC ++的信息,我建议您在NSBrief播客上收听我的客座,我会详细讨论ObjC ++。

或者,是什么原因阻止您将C ++对象放在std::vector而不是NSArray中?您希望将这个充满C ++对象的NSArray用于什么?

PS - 为了完整起见,我还要提一下,+NSNumber numberWithNonretainedPointer:(或者可能是“未获得的”)可以用作预制对象来保持数组中的指针,但是这是不推荐的,因为它在释放时不会在指针上调用delete,所以你必须非常小心,否则你将泄漏C ++对象。最好自己上课。

答案 2 :(得分:1)

如何在Objective-C类中包装C ++对象的小代码示例:

对于看起来像

的C ++类CPP
class CPP {
public:
    std::string aName;
    CPP(std::string aName) : aName(aName) { }
};

您可以创建一个Objective-C包装器类ObjectiveC

// ObjectiveC.h
@interface ObjectiveC : NSObject
{
    CPP *cpp;
}

- (id)initWithString:(NSString*)string;
- (void)print;

@end

//ObjectiveC.mm <- this .mm tells Xcode to use the right compiler
#import "ObjectiveC.h"

@implementation ObjectiveC

- (id)initWithString:(NSString*)string
{
    self = [super init];
    if (self)
    {
        cpp = new CPP([string UTF8String]);
    }
    return self;
}

- (void)print
{
    NSLog(@"%s", cpp->aName.c_str());
}

@end

现在您可以创建一个间接包含C ++对象的NSArray:

// main.mm for example (.m -> .mm !)

ObjectiveC *oc1 = [[ObjectiveC alloc] initWithString:@"oc1"];
ObjectiveC *oc2 = [[ObjectiveC alloc] initWithString:@"oc2"];
ObjectiveC *oc3 = [[ObjectiveC alloc] initWithString:@"oc3"];

NSArray *array = [[NSArray alloc] initWithObjects:oc1, oc2, oc3, nil];

for (ObjectiveC *oc in array) {
    [oc print];
}

一句小话:您必须将包含这些包装文件并与之交互的所有实现文件从.m更改为.mm。第二个选项是在Xcode设置中更改编译器。

相关问题