Objective c 在obj-c中用单例存储实例引用

Objective c 在obj-c中用单例存储实例引用,objective-c,ios,Objective C,Ios,假设我有两个班,A和B。A是单身。我在B中声明了A,所以我可以访问B中方法中的单例变量 B然后创建另一个类的实例,比如C类 然后C创建另一个类的实例,比如说类D 我需要做的是在类D中的类B的实例中运行一个方法,这就是让我发疯的原因 我的第一个想法是在我的单例(类a)中引用类b的实例,类似于 sharedInstance.classBReference = self; …然后在类D中声明单例,然后在类D实例中使用类似的内容 [sharedInstance.classBInstance class

假设我有两个班,A和B。A是单身。我在B中声明了A,所以我可以访问B中方法中的单例变量

B然后创建另一个类的实例,比如C类

然后C创建另一个类的实例,比如说类D

我需要做的是在类D中的类B的实例中运行一个方法,这就是让我发疯的原因

我的第一个想法是在我的单例(类a)中引用类b的实例,类似于

sharedInstance.classBReference = self;
…然后在类D中声明单例,然后在类D实例中使用类似的内容

[sharedInstance.classBInstance classBInstanceMethod];
当然,只要我这么做了

classB *classBReference;
在我的单件游戏的标题中,它给了我一个“未知类型”的游戏,我在这里读到了关于它的内容,因此,我把一个

@class classB;
在@接口上方,然后我可以声明

classB *classBReference;
没有未知类型的错误,但在类B的init方法中,此

sharedInstance.classBReference = self;
仍然给我一个类型错误

在类型为“class A*”(单例)的对象上未找到属性ClassBreeference。您是要访问ivar ClassBreeference吗


我不知道它为什么这么做,解决办法是什么?还是有更好的方法来完成我想做的事情?

错误消息会告诉您答案。您应该将
classbreeference
定义为属性,或者使用
classbreeference
作为ivar。

避免使用全局变量(也称为singleton)听起来会比较容易混淆。当
B
创建
C
时,为
C
提供对
B
的引用。当
C
创建
D
时,为
D
提供对
B
的引用

如果您需要避免保留周期,请反向引用
B
(如果您的部署目标至少为iOS 5.0)或
不安全(如果您的部署目标早于iOS 5.0)。

点和箭头 “点表示法”是Objective-C最近增加的一种表示法,它为访问者提供了一种简写表示法。如果有指向对象(或结构!)的指针,则不能使用
访问其实例变量,而只能使用
->

你的线路

sharedInstance.classBReference = self;
完全一样

[sharedInstance setClassBReference:self];
问题是您没有任何这样的方法
-setClassBreeference:
。为了设置实例变量,必须改为编写

sharedInstance->classBReference = self;
@保护变量 用这一行切换后,您可能(如果您没有将其设置为公共的话)会看到错误

实例变量“
classbreeference
”是私有的

在这种情况下,您需要更改
classA
接口,以便将
classbreeference
声明为
@public
classA
中的实例变量列表应该如下所示

@interface classA : NSObject
{
//@protected
//(The @protected keyword is optional when at the beginning of the list; instance
//variables are protected by default, which is why you're needing to declare your
//instance variable classBReference to be @public (since classB is not a subclass
//of classA and consequently cannot access its protected instance variables).
    //....
    //some protected instance variables
    //....
@private
    //....
    //some private instance variables
    //....
@public
    //....
    //some public instance variables
    classB *classBReference;
    //....
@protected
    //....
    //some more protected instance variables
    //Note that @protected is not optional in order to make the instance variables
    //here be protected since they are declared subsequent to the prior @public.
    //....
}
//....
@end
使用@properties 类引用案例 也就是说,一般认为使用访问器比使用实例变量更好。为此,您应该向
classA
接口添加一个属性:

@interface classA : NSObject
{
    classB *classBReference;
}
@property classB *classBReference;
@end
并合成
classbreeference
属性,以访问
classA
实现中的
classbreeference
实例变量,如下所示:

@implementation classB

@synthesize classBReference = classBReference;
总体结构
@synthesis
有点不清楚,因为我们有一个实例变量和一个同名的属性。需要作出一些澄清。通常,在类的(“
MyObject
”在本例中)
@接口
中声明一个实例变量(
myVariable
”)和一个属性(
myProperty
”)

在类的
@实现中
有一行

@synthesize myProperty = myVariable.
该代码的结果是,给定一个实例

MyObject *object = //...
在班上,一个人会写字

SomeObject *someObject = //...
[object setMyProperty:someObject];
object.myProperty = someObject;
SomeObject *someOtherObject = object.myProperty;

MyObject
实例调用
-setMyProperty:
的结果是
myVariable
设置为等于传递给方法的参数——在本例中为
someObject
。类似地,对
MyObject
的实例调用
-myProperty
的结果是返回
myVariable

它给我们带来了什么? 如果没有
@property
@synthesis
指令,就必须声明方法

- (void)setMyProperty:(SomeObject *)myProperty;
- (SomeObject *)myProperty;
手动并手动定义它们:

- (void)setMyProperty:(SomeObject *)myProperty
{
    myVariable = myProperty;
}

- (SomeObject *)myProperty
{
    return myVariable;
}
@属性
@synthesis
对该代码进行了一些删节。当您使用各种不同的方法时,为您生成的代码量会变得更加有用

注意:关于
@属性
@合成
指令。首先,你不仅可以编写
@synthesis-myProperty
省略变量名,您可以完全省略合成
myProperty
,并且在这两种情况下自动使用的变量名彼此不同

关于点符号的更多信息 问题中的点符号提供了另一层缩写。而不是必须写作

[object setMyProperty:someObject];
SomeObject *someOtherObject = [object myProperty];
你现在可以写作了

SomeObject *someObject = //...
[object setMyProperty:someObject];
object.myProperty = someObject;
SomeObject *someOtherObject = object.myProperty;
同样地,也不必写

[object setMyProperty:someObject];
SomeObject *someOtherObject = [object myProperty];
你现在可以写作了

SomeObject *someObject = //...
[object setMyProperty:someObject];
object.myProperty = someObject;
SomeObject *someOtherObject = object.myProperty;
需要注意的是,这只是符号。虽然当我们“将
object.myProperty
设置为
someObject
”时,它“看起来有点像”我们在做简单的赋值,但事实并非如此。特别是,当我们执行该行时

object.myProperty = someObject;
方法

- (void)setMyProperty:(SomeObject *)someObject
被执行。因此。这是一种方便,但重要的是要记住您的代码正在做什么