【问题标题】:Best way to pass CGFloat by reference to another class通过引用另一个类来传递 CGFloat 的最佳方法
【发布时间】:2020-09-24 06:07:36
【问题描述】:

ClassA 中,我有一个CGFloatx,我想通过引用ClassB 来传递它,这样如果我对ClassA 中的CGFloat 进行更改,它将被反映在ClassB 中对x 的引用。另外,当我将它传递给ClassB 时,我想将其存储为属性。

我曾考虑过使用 CGFloat 指针,但我正在努力找出使其成为属性的正确语法:

@property(nonatomic) CGFloat *x;

然后取消引用它:

self->x

我考虑过使用NSNumber,但无法使用NSNumber 设置值,这样它就会在ClassB 中更新。我曾想过放弃并制作一个包装类来存储CGFloat,但这似乎有点矫枉过正。

执行此操作的最佳模式是什么?

【问题讨论】:

    标签: ios objective-c cocoa-touch


    【解决方案1】:

    我曾想过放弃并制作一个包装类来存储 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 中的newalloc/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 交互时避免接受。在第一和第三选择中,无论您在语义上感觉“正确”,而不是担心性能,都可以。高温

    【讨论】:

      【解决方案2】:

      [NSMutableData dataWithLength:sizeof(CGFloat)] 并将 mutableBytes 转换为 CGFloat*

      你可以实现属性@property(nonatomic) CGFloat x的getter和setter-无需指针

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-20
        • 1970-01-01
        • 2015-05-13
        • 1970-01-01
        • 2011-03-13
        • 2014-04-28
        相关资源
        最近更新 更多