【问题标题】:Should a BOOL ivar be a pointer to allow another class to set it?BOOL ivar 是否应该是允许另一个类设置它的指针?
【发布时间】:2013-05-03 22:04:40
【问题描述】:

我的班级有一个BOOL 属性,需要由另一个班级设置,所以我正在尝试使用指针。我正在为它声明一个属性,如下所示:

@interface SomeClass : SuperClass
{
    BOOL *_shared;
}
@property(nonatomic) BOOL *shared;

这是正确的方法吗?然后我只需像这样设置和访问值:

*self.shared = YES;

或者将其设置为可保留属性的正确方法是什么?

【问题讨论】:

  • 虽然使用起来很糟糕,但这是一个非常好的问题。这条评论是为了防止最近一连串有效的问题被否决,但这些问题是关于如何实施反模式的问题。
  • 确实如此。请不要对这个问题投反对票。 OP 可能做错了事,但这与它是一个坏问题不同。
  • @alastair - 好吧,我有点想问什么是正确的做法。你在说我上面做的事情是错误的,还是在两个视图控制器之间传递一个 BOOL 指针是错误的?
  • @StackOverFlowRider 请参阅下面的 bbum 答案。传递BOOL 指针几乎肯定是错误的。
  • 这是正确的,如果您在某处为BOOL 分配内存。

标签: objective-c encapsulation instance-variables declared-property


【解决方案1】:

不,您不想发送指向实例变量的指针,以便其他类可以设置实例变量。这样做很脆弱并且会破坏封装。这是一种糟糕的设计模式。

这也是完全没有必要的。

如果实例 A 可以“发送指针”到实例 B,那么实例 A 可以轻松地向实例 B 发送对自身的引用。从那里,实例 B 可以简单地执行 [instanceA setShared:YES];

@interface B:UIViewController
@property(strong) A *controllerA;
@end

@interface A:UIViewController
@property BOOL dogDoorEnabled;
@end

@implementation A
...
- (void) doSomething
{
     B *b = .... get an instance of B ...;
     [b setControllerA: self];
}
@end

@implementation B
...
- (void) doSomethingElse
{
    BOOL isCheeseOnFire = ... calculate whether the cheese is burning ...;
    [[self controllerA] setDogDoorEnabled: !isCheeseOnFire];
}
@end

(注意保留循环——如果 A 以某种方式直接或间接保留 B,那么从 B 对 A 的 (strong) 引用将创建一个保留循环。当您想打破该循环时调用 [b setControllerA:nil]。 )

现在,如果出于某种原因您仍然认为需要将指向 A 的内部状态的指针发送到 B,请更新您的问题。

【讨论】:

  • 完全同意。 很少可能有与性能相关的原因破坏封装,但即使在这种情况下,传递 instanceA 并使用 instanceA->shared 也比传递指向成员变量的指针更好。跨度>
【解决方案2】:

我会用

@interface SomeClass { }
@property(nonatomic) NSNumber *shared;
...
self.shared = [NSNumber numberWithBool:YES]; // in the other class
if ([self.shared boolValue]) {...} // in SomeClass where you want to find what is set

【讨论】:

  • 只是一个小提示......你可以使用新的文字语法,所以可以写:self.shared = @(YES);
  • 这是一个很好的答案。养成使用 NSNumber 的习惯,因为它将使您在未来使用 CoreData 的生活更加轻松。 ;-)
  • 完全没有必要将简单的BOOL ivar 转换为NSNumber。这个答案消除了反模式,但并没有真正回答 OP 的问题。
  • 你说得对,简单的@property (nonatomic,assign) BOOL shared; 也可以。
【解决方案3】:

没有。正确的方法是声明 BOOL 而不是指向 BOOL 的指针。当您想将指向 BOOL 的指针发送到下一个 viewController 时,您可以使用运算符 & 发送变量的地址。

在您的界面中:

@interface SomeClass {
    BOOL _shared
}

@property (assign) BOOL _shared ;

在您的实施中:

[nextViewController setPointerToBool: &_shared] ;

【讨论】:

  • 更正了 BOOL 声明。但是使用实例变量的地址作为编辑对象状态的手段是完全错误的做法。
  • @bbum,是的,这不是一件聪明的事情。但这就是他所要求的。
【解决方案4】:

正如其他人所说,您应该只使用 BOOL 而不是指向 BOOL 的指针。将其设为assign 变量,您可以简单地分配给它并直接读取它。此外,在现代编译器中,您不需要声明实例变量,这似乎是一个好习惯。

@interface SomeClass

@property (assign) BOOL shared;

@end

在您的实施中:

self.shared = YES;

当涉及到你的视图控制器时,不要传递一个指向 BOOL 的指针,而是传递一个指向 SomeClass 实例的指针,然后像这样设置它:

someInstance.shared = YES;

【讨论】:

  • OP 需要从某个其他类中设置变量。因此,self.shared = 将不起作用。
  • 他没有与那部分相关的代码,所以很难提供一个简洁的例子。我又加了一行。
猜你喜欢
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 2017-10-19
  • 2023-03-04
  • 1970-01-01
  • 2020-10-10
  • 2020-04-12
  • 2020-05-10
相关资源
最近更新 更多