什么是最好的方式来交流
在NSArray
存储c结构的常用方法是什么? 优点,缺点,内存处理?
值得注意的是, valueWithBytes
和valueWithPointer
什么区别 - 由下面的justin和catfish引发。
以下是Apple讨论valueWithBytes:objCType:
的链接valueWithBytes:objCType:
面向未来的读者...
对于一些横向思考和更多关注性能的问题,Evgen提出了在C ++中使用STL::vector
的问题。
(这引发了一个有趣的问题:是否有一个快速的c库,与STL::vector
不同,但重量更轻,可以实现最小的“整齐处理数组”......)
所以原来的问题...
例如:
typedef struct _Megapoint {
float w,x,y,z;
} Megapoint;
所以:在NSArray
存储自己的结构的正常,最好,惯用的方式是什么,以及如何处理这个习惯用法中的记忆?
请注意,我特意寻找常用的习惯来存储结构。 当然,通过开设一个新的小班可以避免这个问题。 不过,我想知道如何将数组中的结构放入数组中,谢谢。
顺便说一句,这可能是NSData方法吗? 不是最好的...
Megapoint p;
NSArray *a = [NSArray arrayWithObjects:
[NSData dataWithBytes:&p length:sizeof(Megapoint)],
[NSData dataWithBytes:&p length:sizeof(Megapoint)],
[NSData dataWithBytes:&p length:sizeof(Megapoint)],
nil];
顺便说一句,作为一个参考点,并感谢Jarret Hardie,以下是如何在NSArray
存储CGPoints
和类似内容:
NSArray *points = [NSArray arrayWithObjects:
[NSValue valueWithCGPoint:CGPointMake(6.9, 6.9)],
[NSValue valueWithCGPoint:CGPointMake(6.9, 6.9)],
nil];
(请参阅如何以简单的方式将CGPoint对象添加到NSArray?)
NSValue不仅支持CoreGraphics结构 - 您也可以自己使用它。 我建议这样做,因为对于简单的数据结构,类可能比NSData
轻。
只需使用如下所示的表达式:
[NSValue valueWithBytes:&p objCType:@encode(Megapoint)];
为了让价值恢复:
Megapoint p;
[value getValue:&p];
我建议你坚持使用NSValue
路由,但如果你确实希望在你的NSArray(和Cocoa中的其他集合对象)中存储普通的'ol struct
数据类型,你可以这样做 - 尽管间接使用Core Foundation和Toll-免费桥接。
CFArrayRef
(及其可变对象CFMutableArrayRef
)在创建数组对象时为开发人员提供了更大的灵活性。 请参阅指定初始程序的第四个参数:
CFArrayRef CFArrayCreate (
CFAllocatorRef allocator,
const void **values,
CFIndex numValues,
const CFArrayCallBacks *callBacks
);
这允许您请求CFArrayRef
对象使用Core Foundation的内存管理例程,根本不使用,甚至不使用自己的内存管理例程。
强制性的例子:
// One would pass &kCFTypeArrayCallBacks (in lieu of NULL) if using CF types.
CFMutableArrayRef arrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
NSMutableArray *array = (NSMutableArray *)arrayRef;
struct {int member;} myStruct = {.member = 42};
// Casting to "id" to avoid compiler warning
[array addObject:(id)&myStruct];
// Hurray!
struct {int member;} *mySameStruct = [array objectAtIndex:0];
上面的例子完全忽略了关于内存管理的问题。 结构myStruct
在堆栈上创建,因此在函数结束时被销毁 - 数组将包含一个指向不再存在的对象的指针。 你可以通过使用自己的内存管理例程来解决这个问题 - 为什么这个选项会提供给你 - 但是你必须要做引用计数,分配内存,释放内存等等。
我不会推荐这个解决方案,但是如果其他人感兴趣的话,它会保留在这里。 :-)
这里演示了如何使用堆中分配的结构(代替堆栈):
typedef struct {
float w, x, y, z;
} Megapoint;
// One would pass &kCFTypeArrayCallBacks (in lieu of NULL) if using CF types.
CFMutableArrayRef arrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
NSMutableArray *array = (NSMutableArray *)arrayRef;
Megapoint *myPoint = malloc(sizeof(Megapoint);
myPoint->w = 42.0f;
// set ivars as desired..
// Casting to "id" to avoid compiler warning
[array addObject:(id)myPoint];
// Hurray!
Megapoint *mySamePoint = [array objectAtIndex:0];
如果你感到讨厌,或者真的有很多类需要创建:动态构造一个objc类(ref: class_addIvar
)有时候很有用。 这样,你可以从任意类型创建任意的objc类。 你可以指定字段的字段,或者只是传递结构的信息(但实际上复制NSData)。 有时很有用,但对于大多数读者来说可能更多是一个“有趣的事实”。
我将如何在这里应用这个?
您可以调用class_addIvar并将一个Megapoint实例变量添加到新类中,或者可以在运行时综合Megapoint类的objc变体(例如,Megapoint的每个字段的实例变量)。
前者相当于编译的objc类:
@interface MONMegapoint { Megapoint megapoint; } @end
后者相当于编译的objc类:
@interface MONMegapoint { float w,x,y,z; } @end
添加完ivars后,您可以添加/合成方法。
要在接收端读取存储的值,请使用您的合成方法object_getInstanceVariable
或valueForKey:
它通常会将这些标量实例变量转换为NSNumber或NSValue表示形式)。
顺便说一句:所有你收到的答案是有用的,有些更好/更糟糕/无效取决于上下文/情况。 有关内存,速度,易维护性,易于传输或归档等方面的具体需求将决定哪种方案最适合某一特定情况......但没有任何“完美”解决方案在各方面都很理想。 没有'将一个c-struct放入一个NSArray'的最佳方式,只是'将一个c-struct放入一个NSArray中用于特定场景,案例或一组需求的最佳方式' - 指定。
此外,NSArray是一个通常可重用的指针大小(或更小)类型的数组接口,但有许多其他容器更适合用于c-structs(std :: vector是c-structs的典型选择)。
链接地址: http://www.djcxy.com/p/14923.html