我创建了一个Objective-C Singleton类。我在课堂上有一些属性,包括BOOL
属性。出于某些奇怪的原因,我声明的“BOOL
变量”将自身“重置”为设置范围之外的 YES 。
在Singleton类的标题中,使用BOOL
使用以下参数声明@property
:
@property (nonatomic, assign, readonly) BOOL shouldCryptData;
在实现中的Singleton类的@interface
中,我重新定义了与readwrite
相同的属性(因为我需要将它只读取到外部类,而是读取/写入我自己的)。 / p>
@interface SingletonClassName ()
@property (nonatomic, assign, readwrite) BOOL shouldCryptData;
@end
在单例类的初始化期间设置BOOL
属性。我在其中一个init方法中设置它。有多种init方法可以指定是否应该加密数据 - 这只是一个示例,它将在何处设置。只有一个我的init方法调用super,所有其他方法都调用主init。
- (id)init {
self = [super init];
if (self) {
// Brief setup code
[self setShouldCryptData:NO]; // Have also tried using dot-notation and without *self*
// I can confirm that the shouldCryptData property is NO (within the current scope) right after setting it in this method
}
return self;
}
现在,奇怪的部分是当我尝试从任何其他方法访问shouldCryptData
时,它总是返回YES 。在明确将其设置为NO后,为什么会返回YES?
我没有以任何奇怪的方式访问它,就像这样:
if (self.shouldCryptData == YES) // Outside of the init method, this is ALWAYS true
我知道我做错了什么,但我无法理解。我觉得单身人士对此有所了解,但我不确定。似乎Google和StackOverflow都没有任何答案。有什么想法吗?
编辑
单身实施:
//-------- Header ---------------------//
@interface SingletonClassName : NSObject
+ (SingletonClassName *)sharedManager;
@end
//-------- Implementation ------------//
@implementation
+ (SingletonClassName *)sharedManager {
static SingletonClassName *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (sharedManager == nil) sharedManager = [[super allocWithZone:NULL] init];
});
return sharedManager;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self sharedManager];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
答案 0 :(得分:7)
最简单的解释是你没有单身,你在一个实例上设置该属性,在另一个实例上读取它。
尝试在设置和访问属性的所有方法中执行NSLog(@"%p", self)
,并确保它们都是相同的。
<强>加了:强>
这是我通常的单身逻辑:
+ (instancetype) sharedInstance {
static MyClass *singleton;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[self alloc] init];
});
return singleton;
}
在您需要时调用[MyClass sharedInstance]
。
答案 1 :(得分:0)
使用这里的答案和评论中的建议组合,弄清楚发生了什么。 @Paul.s的最佳建议是在属性声明上设置断点:
您确定没有其他设置为YES吗?在属性声明上放置一个断点,每次读取或写入属性时它都会中断
@Andy的评论也有助于弄清楚问题是什么:
您还可以尝试在变量上设置一个观察点,只要变量发生变化,该观察点就会暂停。您可以首先在单例的init方法中设置断点,然后在到达断点时在调试器中键入watchpoint set variable shouldCryptData。
我发现init
方法被多次调用,并且每次都使用不同的BOOL属性设置shouldCryptData
。
另一个suggestion from @noa帮助清理了BOOL属性设置的实例。我最初是从共享管理器设置它,但后来在init
方法中设置它,因为sharedManager
与其他方法不同。以下是答案的相关摘录:
尝试在设置和访问属性的所有方法中执行NSLog(@“%p”,self),并确保它们完全相同。
因此,事实证明存在多个问题:
init
)答案 2 :(得分:-1)
KVO是其中一种方式。我举一个例子。
TestObject.h
@interface TestObject : NSObject
@property (nonatomic, assign) BOOL isIt ;
@end
TestObject.m
@implementation TestObject
- (id)init
{
self = [super init] ;
if (self) {
[self addObserver:self forKeyPath:@"isIt" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil] ;
}
return self ;
}
- (void)dealloc
{
[self removeObserver:self forKeyPath:@"isIt"] ;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"isIt"]) {
NSLog(@"%@", change) ; // add a breakpoint here, you will know where change the value
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context] ;
}
}
@end
只有在通过点符号或setIsIt方法设置属性时才会收到通知。