gpt4 book ai didi

objective-c - 在.m文件下@Implementation和@Interface下声明变量的区别

转载 作者:太空狗 更新时间:2023-10-30 03:41:30 25 4
gpt4 key购买 nike

我学习 Objective-C 有一段时间了。据我了解,我知道当你在 .h 文件@interface 中声明一个变量时,可以公开访问该变量(类似于 java 中的公共(public)变量).

@interface MyObject

@property NSInteger intData;

@end

但是当您在.m 文件@interface 中声明它时。它只能在 @implementation 下的 .m 文件中访问,除非你为它提供 getter 和 setter。

@interface MyObject ()

@property NSInteger intData;

@end

但是我也注意到另一种声明变量的方式,就是在@implementation下声明它

@implementation

NSInteger intData;

@end

而且我发现它的工作方式与在 @interface 下使用 @property 在 .m 文件中声明它的方式相同

我不明白两者之间的区别(在@implementation 下声明和在@interface 下声明(在.m 文件)。

我已经在堆栈中搜索过这个,但他们都在谈论@implementation 和@interface(在.h 文件 中)之间的区别。所以认为这不是重复的。

最佳答案

首先,您没有声明变量;你在申报属性(property)。属性由实例变量支持,但它也添加了方法。以下是对放置变量的位置的解释:

@interface MyClass : NSObject {
NSInteger i ;
}
@end

这是在您的类上放置实例变量的地方。它只能通过您的类和类别的方法访问。 (旁注:它可以从外部访问,但这不是推荐的做法)

另一个例子:

@interface MyClass : NSObject
@end

@implementation MyClass {
NSInteger i ;
}
@end

这也是一个实例变量,但只能通过在该 block 内编写的方法访问。 (旁注:可以通过挖掘类定义来访问它,但这不是推荐(或常见)的​​做法)

另一个例子:

@interface MyClass : NSObject
@property NSInteger i ;
@end

等同于:

@interface MyClass : NSObject {
NSInteger _i ; // you are not allowed to access it by this variable
}
- (NSInteger) i ;
- (void) setI:(NSInteger)value ;
@end

这是一个允许人们获取和设置的属性。您在您的方法或其他方法中将该变量用作:

NSLog ( @"The value is %i" , self.i ) ; // if it's your instance method
NSLog ( @"The value is %i" , object.i ) ; // if it's object's instance method

另一个例子:

@interface MyClass : NSObject {
NSInteger i ;
}
@property NSInteger i ;
@end
@implementation MyClass
@synthesize i ; // Causes the property to line up with the ivar by the same name.
@end

等同于:

@interface MyClass : NSObject {
NSInteger i ; // you ARE allowed to use this since you defined it
}
- (NSInteger) i ;
- (void) setI:(NSInteger)value ;
@end

在这里,您可以使用 getter/setter 方法或实例变量本身。但是,您通常应该使用这些方法,因为您 [隐式] 将它们声明为原子的,因此它们具有线程同步。如果你想让它不做线程(并加速它,只要你不打算在多线程环境中使用它):

@property (nonatomic) NSInteger i ;
@property (nonatomic,readonly) NSInteger i ; // only makes a getter method

我建议暂时避免这种情况并使用直接属性,因为它会帮助您避免很多常见错误。除非您分析您的程序并确定这是性能损失的原因,否则您应该只使用这些属性。

另一个例子:

@interface MyClass : NSObject
@end

@implementation MyClass
NSInteger i ;
@end

不是实例变量。它是一个全局变量,恰好写在您的 @implementation 范围内。

请参阅上文了解如何将其转换为实例变量(即将其放在大括号中)

再补充一点:

像这样声明一个属性:

@interface MyClass ()
@property NSInteger i ;
@end

不会将其设为私有(private)。但是,它隐藏在人们通常无法访问的文件中,因此编译器不知道属性的存在。

代码中其他地方的其他函数仍然可以调用:

[yourObject i] ;

要获取该属性的值 - 但他们必须首先知道它在那里。

附录回答评论中的问题:

默认情况下,属性是原子的。它不一定遵循原子 的严格定义(这是一堆蠕虫,我建议你现在不要看),但具有相同的效果:线程保证看到一个完整的和向上的-最新值,无论另一个线程何时写入它。它通常在合成 getter/setter 方法时这样做:

- (NSInteger) i {
@synchronized(self) {
return i ;
}
}
- (void) setI:(NSInteger)value {
@synchronized(self) {
i = value ;
}
}

如果您改为指定 nonatomic,它将合成这些:

- (NSInteger) i {
return i ;
}
- (void) setI:(NSInteger)value {
i = value ;
}

如果您的属性是 atomic,那么您不应该直接访问 ivar。这样做违反了您一开始就赋予它的线程保护。 (旁注:在某些情况下您可以,但请等到您对线程/同步更加熟悉后再尝试。)

关于objective-c - 在.m文件下@Implementation和@Interface下声明变量的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31895332/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com