Ios Objective-C单例重置中的变量
我创建了一个Objective-C单例类。我在类上有一些属性,包括Ios Objective-C单例重置中的变量,ios,objective-c,variables,properties,singleton,Ios,Objective C,Variables,Properties,Singleton,我创建了一个Objective-C单例类。我在类上有一些属性,包括BOOL属性。出于某种奇怪的原因,我声明的BOOL变量将自身重置为YES中设置的范围之外 在Singleton类的头中,使用带有以下参数的@property声明BOOL: @property (nonatomic, assign, readonly) BOOL shouldCryptData; 在实现中的Singleton类的@接口中,我重新定义了与readwrite相同的属性(因为我需要它只对外部类读,但对自己的类读/写) B
BOOL
属性。出于某种奇怪的原因,我声明的BOOL
变量将自身重置为YES中设置的范围之外
在Singleton类的头中,使用带有以下参数的@property
声明BOOL
:
@property (nonatomic, assign, readonly) BOOL shouldCryptData;
在实现中的Singleton类的@接口
中,我重新定义了与readwrite
相同的属性(因为我需要它只对外部类读,但对自己的类读/写)
BOOL
属性在singleton类初始化期间设置。我在一个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。为什么显式设置为“否”后返回“是”
我不会以任何奇怪的方式访问它,就像这样:
if (self.shouldCryptData == YES) // Outside of the init method, this is ALWAYS true
我知道我做错了什么,但我想不出来。我觉得这和单身汉有关,但我不确定。谷歌和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;
}
最简单的解释是你没有一个单例,你在一个实例上设置这个属性,在另一个实例上读取它 尝试在设置和访问属性的所有方法中执行
NSLog(@“%p”,self)
,并确保它们都相同
添加:
这是我通常的单例逻辑:
+ (instancetype) sharedInstance {
static MyClass *singleton;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[self alloc] init];
});
return singleton;
}
在需要时调用
[MyClass sharedInstance]
。最简单的解释是,您没有一个单独的实例,您在一个实例上设置该属性,然后在另一个实例上读取它
尝试在设置和访问属性的所有方法中执行NSLog(@“%p”,self)
,并确保它们都相同
添加:
这是我通常的单例逻辑:
+ (instancetype) sharedInstance {
static MyClass *singleton;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[self alloc] init];
});
return singleton;
}
需要时调用
[MyClass sharedInstance]
。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方法设置属性时,才会收到通知。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方法设置属性时,您才会收到通知。使用此处的答案和注释中的建议组合来了解发生了什么。根据,最好的建议是在属性声明上放置断点: 您确定没有其他设置将其设置为“是”吗?在属性声明上放置断点,每次读取或写入属性时,该断点都应中断 他的评论也有助于弄清问题所在:
您还可以尝试在变量上设置观察点,该观察点将在变量更改时暂停。您可以首先在singleton的init方法中设置断点,然后在到达断点后在调试器中键入watchpoint set variable shouldCryptData来完成此操作 我发现
init
方法被多次调用,每次都使用不同的BOOL属性设置,shouldCryptData
另一个有助于澄清BOOL属性设置在哪个实例上。我最初从共享管理器设置它,但后来在
init
方法中设置它,因为sharedManager
与其他方法位于不同的实例上。以下是答案的相关摘录:
尝试在设置和访问属性的所有方法中执行NSLog(@“%p”,self),并确保它们都相同
因此,事实证明存在多个问题:
- 属性被设置了多次(对
进行了多次不必要的调用)init
- 原来我最初是在另一个实例上设置属性的
- 我的单例没有正确创建(尽管这并没有真正影响属性)
您还可以尝试在变量上设置观察点,该观察点将在变量更改时暂停。您可以首先在singleton的init方法中设置断点,然后在到达断点后在调试器中键入watchpoint set variable shouldCryptData来完成此操作 我发现
init
方法被多次调用,每次都使用不同的BOOL属性设置,shouldCryptData
另一个有助于澄清BOOL属性设置在哪个实例上。我最初从共享管理器设置它,但后来在
init
方法中设置它,因为sharedManager
与其他方法位于不同的实例上。以下是答案的相关摘录:
尝试在设置和访问属性的所有方法中执行NSLog(@“%p”,self),并确保它们都相同
所以,结果是我们