首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在obj-c中的单例中存储实例引用

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

Stack Overflow用户
提问于 2012-10-30 10:49:58
回答 3查看 232关注 0票数 0

假设我有两个类,A和B。A是一个单例。我在B中声明了A,这样我就可以在B中的方法中访问单例变量。

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

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

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

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

代码语言:javascript
运行
复制
sharedInstance.classBReference = self;

然后..and在类D中声明单例,然后在类D实例中使用类似下面的内容...

代码语言:javascript
运行
复制
[sharedInstance.classBInstance classBInstanceMethod];

当然,当我这么做的时候..

代码语言:javascript
运行
复制
classB *classBReference;

在我的单例的标题中,它对我进行了“未知类型”的游戏,我在这里读到了这个类型,所以我放了一个

代码语言:javascript
运行
复制
@class classB;

在@接口上,然后我可以声明...

代码语言:javascript
运行
复制
classB *classBReference;

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

代码语言:javascript
运行
复制
sharedInstance.classBReference = self;

仍然会给出一个类型错误

“在类型为"class A*”(单例)的对象上找不到属性classBReference。是否要访问ivar classBReference?“

我不知道它为什么要这么做,解决方案是什么?或者有没有更好的方法来做我想做的事情?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-10-30 11:08:39

点和箭头

“点符号”是Objective-C中最近添加的一个符号,它为访问器提供了一种简写符号。如果有指向对象(或结构!)的指针,则不能使用.访问其实例变量,只能使用->访问。

你的产品线

代码语言:javascript
运行
复制
sharedInstance.classBReference = self;

完全相同于

代码语言:javascript
运行
复制
[sharedInstance setClassBReference:self];

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

代码语言:javascript
运行
复制
sharedInstance->classBReference = self;

@受保护的变量

在使用下面这行代码切换行之后,您可能会看到错误(如果您还没有使用@public)

实例变量“classBReference”是私有的

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

代码语言:javascript
运行
复制
@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接口添加一个属性:

代码语言:javascript
运行
复制
@interface classA : NSObject
{
    classB *classBReference;
}
@property classB *classBReference;
@end

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

代码语言:javascript
运行
复制
@implementation classB

@synthesize classBReference = classBReference;

一般设置

因为我们有一个实例变量和一个同名的属性,所以@synthesize不太清楚。一些澄清是必要的。通常,在类的(本例中为“MyObject”)中,@interface声明了一个实例变量(本例中为“myVariable”)和一个属性(本例中为“myProperty”)。

代码语言:javascript
运行
复制
@interface MyObject : NSObject
{
    SomeObject *myVariable;
}
@property SomeObject *myProperty;
@end

在类的@implementation中,有一行

代码语言:javascript
运行
复制
@synthesize myProperty = myVariable.

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

代码语言:javascript
运行
复制
MyObject *object = //...

在这个班级中,一个人能够写

代码语言:javascript
运行
复制
SomeObject *someObject = //...
[object setMyProperty:someObject];

代码语言:javascript
运行
复制
SomeObject *someOtherObject = [object myProperty];

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

它能给我们带来什么?

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

代码语言:javascript
运行
复制
- (void)setMyProperty:(SomeObject *)myProperty;
- (SomeObject *)myProperty;

手动定义,也可以手动定义:

代码语言:javascript
运行
复制
- (void)setMyProperty:(SomeObject *)myProperty
{
    myVariable = myProperty;
}

- (SomeObject *)myProperty
{
    return myVariable;
}

@property@synthesize对此代码进行了一些删节。当您使用各种property attributes时,为您生成的代码量将变得更加有益。

注意:有关于@property@synthesize指令的more to say。首先,您不仅可以省略变量名来编写@synthesize myProperty;,还可以完全省略myProperty的合成,并且在这两种情况下自动使用的变量名是不同的。

关于点符号的更多信息

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

代码语言:javascript
运行
复制
[object setMyProperty:someObject];

现在,您可以编写

代码语言:javascript
运行
复制
object.myProperty = someObject;

类似地,不需要编写

代码语言:javascript
运行
复制
SomeObject *someOtherObject = [object myProperty];

现在,您可以编写

代码语言:javascript
运行
复制
SomeObject *someOtherObject = object.myProperty;

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

代码语言:javascript
运行
复制
object.myProperty = someObject;

该方法

代码语言:javascript
运行
复制
- (void)setMyProperty:(SomeObject *)someObject

将被执行。出于这个原因,dot notation is a subject of some contention。这很方便,但重要的是要记住您的代码正在做什么。

票数 1
EN

Stack Overflow用户

发布于 2012-10-30 11:01:56

错误消息会告诉您答案。您应该将classBReference定义为property,或者将classBReference定义为ivar。

票数 0
EN

Stack Overflow用户

发布于 2012-10-30 11:08:26

通过避免使用全局变量(也就是单例变量),听起来就不会那么困惑了。当C创建B时,为B提供对C的引用。当D创建B时,为C提供对D的引用。

如果需要避免保留周期,请对B进行反向引用:weak (如果您的部署目标至少是iOS 5.0)或unsafe_unretained (如果您的部署目标早于iOS 5.0)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13131977

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档