Objective c 将实例变量的setter/getter传递给类

Objective c 将实例变量的setter/getter传递给类,objective-c,cocoa-touch,uilabel,subclass,message-forwarding,Objective C,Cocoa Touch,Uilabel,Subclass,Message Forwarding,我正在创建一个UIView子类(我称之为MarqueeLabel),当UILabel文本对于包含的视图来说太长时,该子类以字幕方式为子视图UILabel ivar制作动画 我希望有一个干净的实现,而不必在我的marqueelab类中编写方法来设置/检索UILabel ivar的所有标准UILabel(文本、字体、颜色等)实例变量。我找到了一种通过消息转发实现这一点的方法——发送到marqueelab的所有未识别方法都会传递到UILabel ivar。在我的例子中,MarqueeLabel无法识别

我正在创建一个UIView子类(我称之为
MarqueeLabel
),当UILabel文本对于包含的视图来说太长时,该子类以字幕方式为子视图UILabel ivar制作动画

我希望有一个干净的实现,而不必在我的
marqueelab
类中编写方法来设置/检索UILabel ivar的所有标准UILabel(文本、字体、颜色等)实例变量。我找到了一种通过消息转发实现这一点的方法——发送到
marqueelab
的所有未识别方法都会传递到UILabel ivar。在我的例子中,
MarqueeLabel
无法识别的方法是UILabel通常使用的方法

但是,这种方法存在一些问题:
1.您必须使用
[marqueeLabel setText:@“Label here”]
,而不是
marqueeLabel.text

2.编译器在上行给出警告,因为:

“MarqueeLabel”可能不响应“-setText:”

我知道可以忽略它,但会惹恼其他人

为了避免这些问题,有没有办法“提出”ivar中的方法,以便在仍然作用于ivar对象的情况下使用类访问它们

谢谢

注意:我的设置方式可能也不是最好的方式。也许子类化或类继续UILabel会更好,但我无法理解如何使用这些方法完成动画+剪辑(当文本滚动离开包含UIView并消失时)


注2:我知道您可以使用
marqueelab.subLabel.text
其中
subLabel
是子视图UILabel。这可能是我的方向,但不妨看看是否有更好的解决方案

对于属性,您可以在接口中定义属性,并在实现中使用@dynamic,这样就不必创建存根实现。确保您还覆盖了
valueForUndefinedKey:
setValue:forUndefinedKey:
并转发到标签

对于不属于属性的任何方法,可以使用类别来声明该方法,而无需实现它。这将消除警告,但仍使用内置转发

//MarqueeLabel.h
#import <UIKit/UIKit.h>
@interface MarqueeLabel : UIView {}
@property (nonatomic, copy) NSString *text;
@end
@interface MarqueeLabel (UILabelWrapper)
- (void)methodToOverride;
@end

//MarqueeLabel.m
#import "MarqueeLabel.h"
@implementation MarqueeLabel
@dynamic text;
- (id)valueForUndefinedKey:(NSString *)key {
    return [theLabel valueForKey:key];
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    [theLabel setValue:value forKey:key];
}
@end
//MarqueeLabel.h
#进口
@接口MarqueeLabel:UIView{}
@属性(非原子,复制)NSString*文本;
@结束
@接口MarqueeLabel(UILabelWrapper)
-(无效)方法超越;
@结束
//MarqueeLabel.m
#导入“MarqueeLabel.h”
@实现标记
@动态文本;
-(id)valueForUndefinedKey:(NSString*)键{
返回[标签值forkey:key];
}
-(void)设置值:(id)未定义键的值:(NSString*)键{
[标签设置值:值forKey:key];
}
@结束

对于属性,您可以在接口中定义属性,并在实现中使用@dynamic,这样就不必创建存根实现。确保您还覆盖了
valueForUndefinedKey:
setValue:forUndefinedKey:
并转发到标签

对于不属于属性的任何方法,可以使用类别来声明该方法,而无需实现它。这将消除警告,但仍使用内置转发

//MarqueeLabel.h
#import <UIKit/UIKit.h>
@interface MarqueeLabel : UIView {}
@property (nonatomic, copy) NSString *text;
@end
@interface MarqueeLabel (UILabelWrapper)
- (void)methodToOverride;
@end

//MarqueeLabel.m
#import "MarqueeLabel.h"
@implementation MarqueeLabel
@dynamic text;
- (id)valueForUndefinedKey:(NSString *)key {
    return [theLabel valueForKey:key];
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    [theLabel setValue:value forKey:key];
}
@end
//MarqueeLabel.h
#进口
@接口MarqueeLabel:UIView{}
@属性(非原子,复制)NSString*文本;
@结束
@接口MarqueeLabel(UILabelWrapper)
-(无效)方法超越;
@结束
//MarqueeLabel.m
#导入“MarqueeLabel.h”
@实现标记
@动态文本;
-(id)valueForUndefinedKey:(NSString*)键{
返回[标签值forkey:key];
}
-(void)设置值:(id)未定义键的值:(NSString*)键{
[标签设置值:值forKey:key];
}
@结束

完全按照我的想法工作,谢谢!我认为需要以某种方式使用
@dynamic
,但我没有遇到forUndefinedKey方法,只有forwardInvocation。我想你的意思可能是
[标签setValue:value-forKey:key]在最后。我尝试做类似的事情,但是使用getter和setter(在本例中为
marqueelab.text
)并不会在unfinedkey方法中结束。我是做错了什么,还是只是找错了地方?@Bob未定义的键方法仅在某些东西使用KVC(调用
valueForKey:
或相关方法)时使用
marqueeLabel。文本
将被发送到转发机制,因此您需要覆盖NSObject中的选择器:
转发调用:或
转发目标。工作方式与我的想法完全一致,谢谢!我认为需要以某种方式使用
@dynamic
,但我没有遇到forUndefinedKey方法,只有forwardInvocation。我想你的意思可能是
[标签setValue:value-forKey:key]在最后。我尝试做类似的事情,但是使用getter和setter(在本例中为
marqueelab.text
)并不会在unfinedkey方法中结束。我是做错了什么,还是只是找错了地方?@Bob未定义的键方法仅在某些东西使用KVC(调用
valueForKey:
或相关方法)时使用
marqueeLabel.text
将被发送到转发机制,因此您需要从NSObject覆盖
forwardInvocation:
forwardingTargetForSelector: