0

假设我有 2 个班级,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;

在@interface之上,然后我能够声明......

classB *classBReference;

没有未知类型的错误,但是在B类的init方法中,这个...

sharedInstance.classBReference = self;

仍然给我一个类型错误

“在“A 类 *”(单例)类型的对象上找不到属性 classBReference 您是要访问 ivar classBReference 吗?

而且我不知道它为什么这样做,解决方案是什么?还是有更好的方法来做我想做的事情?

4

3 回答 3

1

点和箭头

“点符号”是最近对 Objective-C 的补充,它为访问器提供了一种速记符号。如果您有一个指向对象(或结构!)的指针,则不能使用.但只能使用->.

你的线

sharedInstance.classBReference = self;

完全一样

[sharedInstance setClassBReference:self];

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

sharedInstance->classBReference = self;

@protected 变量

用这个换行后,您可能(如果您还没有成功@public)看到错误

实例变量“ classBReference”是私有的

在这种情况下,您需要更改classA接口,以便将classBReference其声明为@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

classBReference 的案例

话虽如此,通常使用访问器而不是实例变量被广泛认为是一种更好的做法。为此,您应该在classA界面中添加一个属性:

@interface classA : NSObject
{
    classB *classBReference;
}
@property classB *classBReference;
@end

并合成classBReference 属性以访问 的实现中的classBReference 实例变量classA如下所示:

@implementation classB

@synthesize classBReference = classBReference;

一般设置

由于@synthesize我们有一个实例变量和一个同名的属性,所以有点不清楚。一些澄清是有序的。一般来说,在一个类的(MyObject本例中为“”)中@interface声明一个实例变量(myVariable本例中为“”)和一个属性(myProperty本例中为“”)。

@interface MyObject : NSObject
{
    SomeObject *myVariable;
}
@property SomeObject *myProperty;
@end

在班上的@implementation一个有行

@synthesize myProperty = myVariable.

这段代码的结果是,给定一个实例

MyObject *object = //...

班上,一个会写

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

SomeObject *someOtherObject = [object myProperty];

调用-setMyProperty:实例的MyObject结果myVariable是设置等于传递给方法的参数——在这种情况下someObject。同样,调用-myProperty实例的结果MyObject就是myVariable返回。

它带给我们什么?

如果没有@propertyand@synthesize指令,就必须声明方法

- (void)setMyProperty:(SomeObject *)myProperty;
- (SomeObject *)myProperty;

手动并手动定义它们:

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

- (SomeObject *)myProperty
{
    return myVariable;
}

@property@synthesize提供此代码的一些删节。当您使用各种属性属性时,为您生成的代码量变得更加有益。

注意:关于and指令还有更多要说的。首先,不仅可以省略变量名,还可以完全省略综合,这两种情况下自动使用的变量名是不同的。 @property@synthesize@synthesize myProperty;myProperty

关于点符号的更多信息

您问题中的点符号提供了另一层缩写。而不是必须写

[object setMyProperty:someObject];

你现在可以写了

object.myProperty = someObject;

同样,不必写

SomeObject *someOtherObject = [object myProperty];

你现在可以写了

SomeObject *someOtherObject = object.myProperty;

重要的是要注意这只是符号。虽然它“有点像”当我们“设置object.myProperty等于someObject”时我们正在做简单的赋值,但事实并非如此。特别是,当我们执行该行时

object.myProperty = someObject;

方法

- (void)setMyProperty:(SomeObject *)someObject

被执行。出于这个原因, 符号 一些争论 主题 这是一种方便,但重要的是要记住您的代码在做什么。

于 2012-10-30T03:08:39.223 回答
0

错误信息告诉你答案。您应该定义classBReference为属性或classBReference用作 ivar。

于 2012-10-30T03:01:56.240 回答
0

听起来你会通过避免全局变量(又名单例)来减少困惑。当创建. C_ B_ 当创建. _ _BCDBCD

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

于 2012-10-30T03:08:26.153 回答