我曾想过放弃并制作一个包装类来存储 CGFloat,但这似乎有点过头了。
这种方法的优点是安全,您创建一个对象,两个类都引用它,而 ARC 负责内存管理。
类很容易定义,例如:
@interface ABShare1 : NSObject
@property CGFloat x;
@end
@implementation ABShare1
@end
(在 .h 和 .m 文件中 - 其他示例相同)
使用它的类会是这样的:
@implementation ClassA
{
ABShare1 *one;
}
...
one = ABShare1.new; // somewhere in initialisation
...
... one.x = 42; ... z = one.x * 24; ...
注意:以上将ABShare1引用存储在私有实例变量中,如果您愿意,可以将其存储在属性中,但没有必要。
您可以在传递对象的另一个类上调用方法,例如:
ClassB *myB;
...
[myB using:(ABShare1 *)sharedVariable];
并且其他类可以根据需要保留引用,内存管理是自动的。
我考虑过使用 CGFloat 指针
这是“通过引用”的标准 C(Objective-C 的子集)方式。
您可以将CGFloat * 存储在属性中,Objective-C 中的所有“对象”值属性都只存储指针(例如,@property NSString *name; 存储指向NSString 对象的指针)。
您必须创建CGFloat * 引用的变量,相当于Objective-C 中的new 或alloc/init。您可以使用变量的地址,例如类似:
CGFloat actualX;
CGFloat *x = &actualX;
但您必须手动确保引用的变量 actualX 的生命周期至少与存储在 x 中的指针的使用时间一样长 - 不这样做会导致 悬空指针。
另一个选项是动态分配存储,直接相当于new,例如类似:
CGFloat *x = malloc(sizeof(CGFloat));
但是,您现在负责确定何时不再需要存储并释放它(使用free())。
第一个解决方案是“矫枉过正”——也许是因为当您摆脱了对内存管理的担忧时,您没有获得“变量”,而是获得/设置值的两个函数/方法。
第二种解决方案最接近“变量”的感觉,您只需使用*sharedVariable 而不是sharedVariable。然而,虽然所需的手动内存管理是 C 程序员的标准,但它不适用于 Objective-C 程序员。
第三种方法混合使用 C 中的结构 (struct) 的两种方法:共享一组变量而不是按地址单独共享每个变量,而是定义一个 struct 并为每个变量定义一个成员变量,分配一个并共享其地址,例如:
typedef struct ABShare
{ CGFloat x;
CGFloat y;
} ABShare;
ABShare *one = malloc(sizeof(ABShare));
one->x = 42;
one->y = 24;
上面和第二个解决方案有同样的内存管理问题,但是我们可以把它转换成一个非常接近的Objective-C等价物:
@interface ABShare : NSObject
{
@public // required
CGFloat x;
CGFloat y;
}
@end
@implementation ABShare
@end
注意:Objective-C 类是使用 structs 有效实现的,事实上,第一个 Objective-C 编译器实际上将它们翻译成 C struct 代码。
使用这个非常接近C:
ABShare *one = ABShare.new;
one->x = 42;
one->y = 24;
“变量”外观与 C 相同,但具有自动内存管理功能。
最后一种方案本质上是 Objective-C 在创建块时管理共享变量的方式——块访问的所有局部变量都被移动到动态分配的对象/结构中,然后使用 -> 访问变量。
Objective-C 中哪个最好?第一个和第三个都是“Objective-C”风格,第二个通常在与 C API 交互时避免接受。在第一和第三选择中,无论您在语义上感觉“正确”,而不是担心性能,都可以。高温