Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.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 将实例变量分配给自身_Ios_Objective C - Fatal编程技术网

Ios 将实例变量分配给自身

Ios 将实例变量分配给自身,ios,objective-c,Ios,Objective C,在我的学校班级中,我有一个实例变量mTeacher: @interface School : NSObject { Teacher *mTeacher; } @end 在实现文件中,我有一个方法-(Teacher*)getTeacher,它应该返回现有的教师实例(如果有),或者创建一个并返回它: - (Teacher *)getTeacher { if (mTeacher != nil) { return mTeacher; } return

在我的
学校
班级中,我有一个实例变量
mTeacher

@interface School : NSObject {
     Teacher *mTeacher;
}
@end
在实现文件中,我有一个方法
-(Teacher*)getTeacher
,它应该返回现有的教师实例(如果有),或者创建一个并返回它:

- (Teacher *)getTeacher {
    if (mTeacher != nil) {
        return mTeacher;
    }
    return [[Teacher alloc] init];
}
可能有多个其他实例方法调用此方法以获取
Teacher
实例并分配给
mTeacher
实例变量:

- (void)methodOne {
   mTeacher = [self getTeacher];
   ...
}

- (void)methodTwo {
   mTeacher = [self getTeacher];
   ...
}

因此,如果其中一个方法已经将
Teacher
的一个实例分配给
mTeacher
,那么调用
[self-getTeacher]
时的另一个方法将以下面的
mTeacher=mTeacher
结束(因为在这种情况下
-(Teacher*)getTeacher
方法只返回
mTeacher
)。我的问题是,在objective-C中可以吗?我的
getTeacher
方法有任何潜在问题吗?

目标c没有问题。。!!我想你不应该对这件事有异议,但你可以问一下,如果不是这样的话

 - (void)methodOne {

    if(!mTeacher){
    mTeacher = [self getTeacher];
    }
    ...
  }
因此,如果
mTeacher
不是
nil
,那么只有它会被调用
getTeacher


在目标c中,您可以为此使用
属性。它将设置它的getter和setter方法。或者需要在init方法中初始化此对象一次。不需要这样做。

看起来您希望延迟实例化变量

Objective-C中的常见模式是声明一个只读(非原子)属性,并使用backing实例变量进行初始化

@interface School : NSObject 

@property (readonly, strong, nonatomic) Teacher *mTeacher;

@end

@implementation School
@synthesize mTeacher = _mTeacher;

- (Teacher *)mTeacher {
    if (!_mTeacher) {
        _mTeacher = [[Teacher alloc] init];
    }
    return _mTeacher;
}

@end
编辑:不使用属性直接访问实例变量:

@interface School : NSObject
{
  Teacher *mTeacher;
}

@end

@implementation School

- (Teacher *)mTeacher {
  if (!mTeacher) {
     mTeacher = [[Teacher alloc] init];
  }
  return mTeacher;
}

@end
但是,如果要显式使用getter而不是实例变量,则必须编写

[self mTeacher];

这种方法没有错,为什么不能在学校初始化中创建教师对象呢。此外,如果您在多线程环境中工作,请确保您没有多次创建教师对象。

方法是正确的,但有两点需要注意:

答:你永远不会有一个“没有老师”的scheool,这意味着财产为零——不管是什么

B.显然,你从另一种语言的Objective-C开始:

  • 不要使用
    m
    前缀作为“成员”。(他们不是成员,而是IVAR。)

  • 不要在接口中声明IVAR

  • 不要为getter使用
    get
    前缀

您可以使用vadian提到的属性:

@interface School : NSObject 
@property (readonly, strong, nonatomic) Teacher *teacher; // without m
- (Teacher*)teacher; // *Alternatively* without @property
@end

@implementation School
// usually the ivar is created implicitly with the name _teacher. 
// However, you have a readonly property and overwrite all accessors 
// (in the case of a read only property there is only a getter) of the property, 
// no ivar will be created automatically. You have to do that explicitly.
{
    Teacher *_teacher;
}

- (Teacher *)teacher { // no m
  if (!_teacher) 
  {  
    _teacher = [[Teacher alloc] init];
  }
  return _teacher;
}
@end

此外,此代码不是线程安全的

您正在实现单例设计模式。下面是关于这个主题的另一篇相关文章,应该会有所帮助:我看不出它在技术上有什么问题,但是为什么不在
init
方法中初始化变量一次,并在需要的地方使用它,而不是尝试多次设置它呢?(关于风格:将
teacher
设置为属性而不是显式变量更符合Objective-C。然后,随着我关于
init
的建议,“getter”将从您的代码中消失。)如果
mTeacher
从不
nil,为什么不在
School
init
方法中初始化它呢?另外,你应该看看这个,我很想知道不使用
@property
进行延迟初始化的版本,你能给我看看吗?我添加了一个示例that@vadian如果覆盖所有访问器,您的示例将无法编译,因为ivar不是隐式创建的。@Aminegm Awad,谢谢,我更喜欢合成。但是,你必须明确地这样做,就像你在编辑中所做的那样。你是对的,代码不是线程安全的。但是,在许多情况下,仅使访问器线程安全是毫无意义的。(这就是几乎没有人使用原子访问器的原因。)然而,如果你想实现线程安全性,现在就应该使用GCD。我的意思是我们应该在创建实例的地方(init方法),而不是访问器来保护线程。@Feroz:惰性初始化非常有用,在很多情况下是必要的。@gnasher729:同意。我不否认这一点,我只是告诉你,在创建实例时要确保线程安全,这句话有什么不对吗?