我完全理解使用@syntesize指令创建getter和setter方法的概念(即如果我有@property int width和@synthesize width,我无意中创建了一个宽度的getter方法和setWidth的setter方法:).
但是,当我没有使用@synthesize指令但是在@implementation部分中声明实例变量是对象时,我并不完全理解访问器方法的工作原理.这是我对以下代码不了解的内容:
1)在主要地方它说:
NSLog(@"Origin at (%i,%i)",myRect.origin1.x,myRect.origin1.y);
在我看来好像它会调用[[myRect origin1] x]方法,它首先确定[myRect origin1]返回原点然后立即调用[origin x]作为结果(然后对y执行相同操作) ).现在,让我失望的是,如果我要更改getter方法的名称
-(XYpoint *) origin1;
包含在Rectangle.h中
-(XYpoint *) origin2;
程序得到大量错误并停止编译.注意:我还在所引用的任何地方更改了此方法的名称,包括将main中的前面的代码更改为
NSLog(@"Origin at (%i,myRect.origin2.x,myRect.origin2.y);
-(void) setOrigin1: (XYpoint *) pt
至:
-(void) setOrigin2: (XYpoint *) pt
然后一切都像以前一样有效.在我看来,只有当我的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
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
XYpoint.h:
#import <Foundation/Foundation.h> @interface XYpoint : NSObject @property int x,y; -(void) setX: (int) xVal andY: (int) yVal; @end
XYpoint.m:
#import "XYpoint.h" @implementation XYpoint @synthesize x,y; -(void) setX: (int) xVal andY: (int) yVal { x = xVal; y = yVal; } @end
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,myRect.origin1.y); NSLog(@"Area = %i,Perimeter = %i",[myRect area],[myRect perimeter]); } return 0; }
解决方法
#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; }
显然,我们希望这个程序运行并使用参数:test调用输出-setIdVar.而这恰恰是在没有ARC的情况下编译它时会发生的事情(例如,使用clang -framework Foundation main.m).
但是如果我们用ARC编译它,clang会崩溃. (clang -framework Foundation -fobjc-arc main.m)
有趣的是,当使用setter作为非对象类型(例如int)或定义了getter时,不会发生这种崩溃.