我已经广泛阅读了已经发布的问题,并且找不到我正在寻找的答案.
我完全理解使用该@syntesize指令创建getter和setter方法的概念(即如果我有,@property int width并且@synthesize width,我无意中创建了getter方法width和setter方法setWidth:).
但是,当我没有使用该@synthesize指令但是在作为@implementation对象的部分中声明实例变量时,我并不完全理解存取器方法的工作原理.这是我对以下代码不了解的内容:
1)在main哪里说:
NSLog(@"Origin at (%i, %i)", myRect.origin1.x, myRect.origin1.y);
Run Code Online (Sandbox Code Playgroud)
在我看来,好像它将调用[[myRect origin1] x]首先确定[myRect origin1]返回的方法,origin然后立即调用[origin x](然后执行相同的操作y).现在,让我失望的是,如果我要更改getter方法的名称
-(XYpoint *) origin1;
Run Code Online (Sandbox Code Playgroud)
包含在Rectangle.h中
-(XYpoint *) origin2;
Run Code Online (Sandbox Code Playgroud)
程序得到大量错误并停止编译.注意:我还在所引用的任何地方更改了此方法的名称,包括将main中的前面的代码更改为
NSLog(@"Origin at (%i, %i)", myRect.origin2.x, myRect.origin2.y);
Run Code Online (Sandbox Code Playgroud)
但是,如果我还更改了setter方法的名称:
-(void) setOrigin1: (XYpoint *) pt
Run Code Online (Sandbox Code Playgroud)
至:
-(void) setOrigin2: (XYpoint *) pt
Run Code Online (Sandbox Code Playgroud)
然后一切都像以前一样有效.在我看来,只有当我的getter和setter都在x setX命名约定中命名时它才能正常工作.我认为这主要是我需要解释的:
A)如果我创建一个碰巧是对象的实例变量(在这种情况下就像'origin'),我必须为它创建getter和setter方法吗?
B)我可以创建一个getter方法但不能创建setter方法,反之亦然
C)如果我确实为'origin'创建了getter和setter方法,那么它们都必须以这种x setX方式命名.在这种情况下作为-(XYpoint *) origin1和-(void) setOrigin1: (XYpoint *) pt.如果我更改了getter的名称,我必须相应地更改setter的名称?
这是所有代码:
Rectangle.h:
#import <Foundation/Foundation.h>
@class XYpoint;
@interface Rectangle : NSObject
@property int width, height;
-(XYpoint *) origin1;
-(void) setOrigin1: (XYpoint *) pt;
-(void) setWidth: (int) w andHeight: (int) h;
-(int) area;
-(int) perimeter;
@end
Run Code Online (Sandbox Code Playgroud)
Rectangle.m:
#import "Rectangle.h"
@implementation Rectangle
{
XYpoint *origin;
}
@synthesize width, height;
-(void) setWidth:(int) w andHeight:(int)h
{
width = w;
height = h;
}
-(void) setOrigin1: (XYpoint *) pt
{
origin = pt;
}
-(int) area
{
return width * height;
}
-(int) perimeter
{
return (width + height) * 2;
}
-(XYpoint *) origin1
{
return origin;
}
@end
Run Code Online (Sandbox Code Playgroud)
XYpoint.h:
#import <Foundation/Foundation.h>
@interface XYpoint : NSObject
@property int x, y;
-(void) setX: (int) xVal andY: (int) yVal;
@end
Run Code Online (Sandbox Code Playgroud)
XYpoint.m:
#import "XYpoint.h"
@implementation XYpoint
@synthesize x,y;
-(void) setX: (int) xVal andY: (int) yVal
{
x = xVal;
y = yVal;
}
@end
Run Code Online (Sandbox Code Playgroud)
main.m文件:
#import <Foundation/Foundation.h>
#import "Rectangle.h"
#import "XYpoint.h"
int main (int argc, const char * argv[])
{
@autoreleasepool {
Rectangle *myRect = [[Rectangle alloc] init];
XYpoint *myPoint = [[XYpoint alloc] init];
[myPoint setX: 100 andY: 200];
[myRect setWidth: 5 andHeight:8];
myRect.origin1 = myPoint;
NSLog(@"Rectangle w = %i, h = %i", myRect.width, myRect.height);
NSLog(@"Origin at (%i, %i)", myRect.origin1.x, myRect.origin1.y);
NSLog(@"Area = %i, Perimeter = %i", [myRect area], [myRect perimeter]);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
A)如果我创建一个碰巧是对象的实例变量(在这种情况下就像'origin'),我必须为它创建getter和setter方法吗?
不可以.如果您声明属性,则需要提供自己的访问者或使用@synthesize指令来创建它们.但是你可以拥有你喜欢的所有实例变量而不需要访问它们.
B)我可以创建一个getter方法但不能创建setter方法,反之亦然
是的,如果您声明您的财产,您可以提供吸气剂readonly.
C)如果我确实为'origin'创建了getter和setter方法,那么它们都必须以x setX方式命名.在这种情况下,作为 - (XYpoint*)origin1和 - (void)setOrigin1:(XYpoint*)pt.如果我更改了getter的名称,我必须相应地更改setter的名称?
您可以为访问者提供自己的名称,但如果您希望您的类符合相关属性的键值编码,则应遵循通常的约定:
@property (getter=isBar, setter=setBar) int bar;
Run Code Online (Sandbox Code Playgroud)
经过电子邮件讨论后,我们发现这个问题实际上似乎是 clang 中的一个错误。考虑以下小程序:
#import <Foundation/Foundation.h>
@interface TestObject : NSObject
-(void)setIdVar:(id)someId;
@end
@implementation TestObject
-(void)setIdVar:(id)someId;
{
NSLog(@"-setIdVar called with argument: %@", someId);
}
@end
int main (int argc, const char * argv[])
{
@autoreleasepool {
TestObject *testObj = [[TestObject alloc] init];
testObj.idVar = @"test";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
显然,我们期望这个程序运行并输出-setIdVar called with argument: test。这正是在不使用 ARC 的情况下编译它时发生的情况(例如使用clang -framework Foundation main.m)。
但如果我们用 ARC 编译它,clang 就会崩溃。( clang -framework Foundation -fobjc-arc main.m)
有趣的是,当对非对象类型(例如 int)使用 setter 或定义 getter 时,不会发生这种崩溃。
| 归档时间: |
|
| 查看次数: |
3093 次 |
| 最近记录: |