mar*_*n's 7 iphone objective-c
@interface some_class : some_parent {
}
@property (nonatomic, assign) CGRect the_rect;
@end
...
@implementation some_class
@synthesize the_rect;
@end
Run Code Online (Sandbox Code Playgroud)
创建some_class的实例后:
instance_of_some_class.the_rect.origin.x = 0.0;
Run Code Online (Sandbox Code Playgroud)
这会生成"表达式无法分配"错误.
当然这很好用:
instance_of_some_class.the_rect = CGRectMake(0,0,0,0);
Run Code Online (Sandbox Code Playgroud)
我想问题是,自动神奇创建的setter只知道将CGRect分配给"the_rect".好的,我明白了.我可以告诉它不要创建一个setter,这样我就可以直接访问成员变量并对struct成员进行赋值而不必分配整个CGRect吗?
我想我可以将它分解为四个单独的CGFloats for origin.x,origin.y,size.width和size.height ...但是你会认为有一种方法可以用CGRects来做到这一点.
令人困惑的是,这当然可行:
CGRect test = instance_of_some_class.the_rect.origin.x;
Run Code Online (Sandbox Code Playgroud)
换句话说,getter知道如何导航struct并提取其中一个元素的值,以便我可以使用它.相反的情况似乎并非如此,因为你无法进入一个恰好是结构的ivar,并且无需分配整个结构就可以对其中一个元素进行赋值.
我也试过这个:
@interface some_class : some_parent {
@public
CGRect the_rect;
}
@property (nonatomic, assign) CGRect the_rect;
@end
Run Code Online (Sandbox Code Playgroud)
在另一个模块中实例化之后:
instance.the_rect->origin.x = some_value;
Run Code Online (Sandbox Code Playgroud)
...并且得到一个错误,说被引用的成员不是指针.我尝试使用instance.the_rect的地址......但这也不起作用.
EDIT TO CLARIFY:这是关于创建一个类似于结构的ivars的类.然后,在将类实例化到其他地方后,您希望能够直接对struct ivar元素进行赋值:
class_instance.struct_ivar.element = something;
Run Code Online (Sandbox Code Playgroud)
我正在使用CGRect作为一个众所周知的结构的一个方便的例子,人们可能希望将其用作ivar.
Dav*_*ong 12
所以你知道如何解决你的问题,但是这就是你必须这样做的原因以及为什么Objective-C中的点语法是一种邪恶的变态的原因之一:
anInstance.property = blah 编译为完全相同的代码,如果你改为输入将生成: [anInstance setProperty:blah]
如果您的属性只是对象属性,则此方法正常.对我们来说不幸的是,点语法在C中已经具有不相关的含义,而这是为了访问结构的成员.即,你可以这样做:
NSRect foo;
foo.origin.x = 42;
Run Code Online (Sandbox Code Playgroud)
如果foo是一个对象,那么foo.origin.x = 42将是相同的[[foo origin] setX:42](假设origin也是一个对象).但是,由于它们只是结构,它只是进行偏移计算并直接在内存中设置值.没有方法调用.
在Objective-C中输入点语法.现在我们有点运算符的两个不同含义(甚至连C++都不允许这样做,具有讽刺意味的是,它的所有运算符都被重载).有时您使用它来访问结构成员.有时您正在使用它来调用对象访问器.有时您可以混合使用这些用途.有时你不能.
如果表达式用作右值,则可以混合使用成员与访问者访问.换句话说,你可以这样做:
foo = anObject.frame.origin.x;
Run Code Online (Sandbox Code Playgroud)
但是,如果您尝试将此作为左值,则会失败:
anObject.frame.origin.x = foo;
Run Code Online (Sandbox Code Playgroud)
解决这个问题的方法是:
NSRect frame = anObject.frame;
frame.origin.x = 42;
anObject.frame = frame;
Run Code Online (Sandbox Code Playgroud)
当然,如果你只是忘记了点语法完全存在,那么你就永远不会遇到这个问题,因为尝试使用括号语法提出一种方法是非常不合情理的.
这是我认为点语法是一个可怕的错误的众多原因之一.如果从未添加过,你永远不会对此感到困惑.
您通常不直接从类外部访问成员变量.您可以将其声明为@public您真正想要的.我想你可能必须为每个rect的成员创建访问器:
- (void)setTheRectX:(CGFloat)newX {
the_rect.origin.x = newX;
}
- (void)setTheRectY:(CGFloat)newY {
the_rect.origin.y = newY;
}
- (void)setTheRectOrigin:(CGPoint)newOrigin {
the_rect.origin = newOrigin;
}
Run Code Online (Sandbox Code Playgroud)
等等.
问题在于,当你要求实例时the_rect,你没有获得指向实例所具有的同一个矩形的指针,就像你将ivar作为一个对象指针一样 - 你得到一个新的结构副本.
公共伊娃:
@interface RectHolder : NSObject {
@public
CGRect the_rect;
}
Run Code Online (Sandbox Code Playgroud)
访问:
RectHolder * myRH = [[RectHolder alloc] init];
myRH->the_rect = CGRectMake(0.0, 0.0, 100, 100);
myRH->the_rect.origin.x = 10;
NSLog(@"%@", NSStringFromRect(myRH->the_rect));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5379 次 |
| 最近记录: |