Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Objective-C单例重置中的变量_Ios_Objective C_Variables_Properties_Singleton - Fatal编程技术网

Ios 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

我创建了一个Objective-C单例类。我在类上有一些属性,包括
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),并确保它们都相同

所以,结果是我们