ios 在类别界面/实现中设置新属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4098753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
setting new properties in category interface/implementation
提问by Thomas Clayson
Ok, so I have this, but it wont work:
好的,所以我有这个,但它不起作用:
@interface UILabel (touches)
@property (nonatomic) BOOL isMethodStep;
@end
@implementation UILabel (touches)
-(BOOL)isMethodStep {
return self.isMethodStep;
}
-(void)setIsMethodStep:(BOOL)boolean {
self.isMethodStep = boolean;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if(self.isMethodStep){
// set all labels to normal font:
UIFont *toSet = (self.font == [UIFont fontWithName:@"Helvetica" size:16]) ? [UIFont fontWithName:@"Helvetica-Bold" size:16] : [UIFont fontWithName:@"Helvetica" size:16];
id superView = self.superview;
for(id theView in [(UIView *)superView subviews])
if([theView isKindOfClass:[UILabel class]])
[(UILabel *)theView setFont:[UIFont fontWithName:@"Helvetica" size:16]];
self.font = toSet;
}
}
@end
If I take out the getter and setter methods then it doesn't work it tells me I need to create some getter and setter methods (or use @synthesize - but putting @synthesize in the @implementation throws an error too). But with the getter and setter methods I get an EXC_BAD_ACCESS and a crash. Any ideas? Thanks
如果我取出 getter 和 setter 方法,那么它不起作用,它告诉我需要创建一些 getter 和 setter 方法(或使用 @synthesize - 但将 @synthesize 放入 @implementation 也会引发错误)。但是使用 getter 和 setter 方法,我得到了 EXC_BAD_ACCESS 和崩溃。有任何想法吗?谢谢
Tom
汤姆
回答by vikingosegundo
It is not possible to add members and properties to an existing class via a category — only methods.
不可能通过类别向现有类添加成员和属性——只有方法。
One possible workaround is to write "setter/getter-like" methods, that uses a singleton to save the variables, that would had been the member.
一种可能的解决方法是编写“setter/getter-like”方法,该方法使用单例来保存变量,这本来是成员。
-(void)setMember:(MyObject *)someObject
{
NSMutableDictionary *dict = [MySingleton sharedRegistry];
[dict setObject:someObject forKey:self];
}
-(MyObject *)member
{
NSMutableDictionary *dict = [MySingleton sharedRegistry];
return [dict objectforKey:self];
}
or — of course — write a custom class, that inherits from UILabel
或者——当然——编写一个自定义类,从 UILabel 继承
Note that nowadays an associated objectcan be injected during runtime. The Objective C Programming Language: Associative References
请注意,现在可以在运行时注入关联对象。Objective C 编程语言:关联参考
回答by Kirow
Checked all answers and did not find the most common solution:
检查了所有答案,没有找到最常见的解决方案:
#import <objc/runtime.h>
static void const *key;
@interface ClassName (CategoryName)
@property (nonatomic) BOOL myProperty;
@end
@implementation ClassName (CategoryName)
- (BOOL)myProperty {
return [objc_getAssociatedObject(self, key) boolValue];
}
- (void)setMyProperty:(BOOL)value {
objc_setAssociatedObject(self, key, @(value), OBJC_ASSOCIATION_RETAIN);
}
@end
swift:
迅速:
private struct AssociatedKeys {
static var keyName = "keyName"
}
extension Foo {
var bar: Any! {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.keyName)
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.keyName , newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
回答by Lal Krishna
You could inject an associated object during runtime.
您可以在运行时注入关联的对象。
#import <objc/runtime.h>
@interface UIView (Private)
@property (nonatomic, assign) CGPoint initialTouchPoint;
@property (nonatomic, strong) UIWindow *alertWindow;
@end
@implementation UIView (Private)
@dynamic initialTouchPoint, alertWindow;
- (CGPoint)initialTouchPoint {
return CGPointFromString(objc_getAssociatedObject(self, @selector(initialTouchPoint)));
}
- (void)setInitialTouchPoint:(CGPoint)initialTouchPoint {
objc_setAssociatedObject(self, @selector(initialTouchPoint), NSStringFromCGPoint(initialTouchPoint), OBJC_ASSOCIATION_RETAIN);
}
- (void)setAlertWindow:(UIWindow *)alertWindow {
objc_setAssociatedObject(self, @selector(alertWindow), alertWindow, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIWindow *)alertWindow {
return objc_getAssociatedObject(self, @selector(alertWindow));
}
@end
回答by Guilherme
There is actually a way, which may not be ideal, but does work.
For it to work, you will need to create a category for a class X and can only be used on subclassesof the same X (e.g. category UIView (Background)
can be used with class MyView : UIView
, but not directly with UIView
)
其实有一种方法,虽然不太理想,但确实有效。
要使其工作,您需要为类 X 创建一个类别,并且只能用于同一个 X 的子类(例如,类别UIView (Background)
可以与 class 一起使用MyView : UIView
,但不能直接与 一起使用UIView
)
// UIView+Background.h
@interface UIView (Background)
@property (strong, nonatomic) NSString *hexColor;
- (void)someMethodThatUsesHexColor;
@end
// UIView+Background.h
@implementation UIView (Background)
@dynamic hexColor; // Must be declared as dynamic
- (void)someMethodThatUsesHexColor {
NSLog(@"Color %@", self.hexColor);
}
@end
Then
然后
// MyView.m
#import "UIView+Background.h"
@interface MyView : UIView
@property (strong, nonatomic) NSString *hexColor;
@end
@implementation MyView ()
- (void)viewDidLoad {
[super viewDidLoad];
[self setHexColor:@"#BABACA"];
[self someMethodThatUsesHexColor];
}
@end
Using this method, you will need to "redeclare" your properties, but after that, you can do all of its manipulation inside your category.
使用此方法,您将需要“重新声明”您的属性,但之后,您可以在您的类别中进行所有操作。
回答by mikeho
It seems as if since Xcode 7(7.0.1, 7A1001), properties are supported in categories. I noticed that Xcodegenerates categories now for Core Datasubclasses.
似乎从Xcode 7(7.0.1, 7A1001) 开始,类别就支持属性。我注意到Xcode现在为Core Data子类生成类别。
For example, I got the files:
例如,我得到了文件:
Location+CoreDataProperties.h
位置+CoreDataProperties.h
#import "Location.h"
NS_ASSUME_NONNULL_BEGIN
@interface Location (CoreDataProperties)
@property (nullable, nonatomic, retain) NSNumber *altitude;
@property (nullable, nonatomic, retain) NSNumber *latitude;
@property (nullable, nonatomic, retain) NSNumber *longitude;
@end
NS_ASSUME_NONNULL_END
Location+CoreDataProperties.m
位置+CoreDataProperties.m
#import "Location+CoreDataProperties.h"
@implementation Location (CoreDataProperties)
@dynamic altitude;
@dynamic latitude;
@dynamic longitude;
@end
So looks like properties in categories might work now. I haven't tested on non-Core Dataclasses.
所以看起来类别中的属性现在可能会起作用。我还没有对非核心数据类进行测试。
What I've noticed is that they do include the category file back into the original class:
我注意到的是,他们确实将类别文件包含在原始类中:
Location.h
位置.h
@interface Location : NSManagedObject
@end
#import "Location+CoreDataProperties.h"
This allows the original class to edit the properties specified by the category.
这允许原始类编辑由类别指定的属性。
回答by Maxim Chetrusca
EDIT: Warning: This property would have a unique value for all the instances of the class.
编辑:警告:对于该类的所有实例,此属性将具有唯一值。
This worked for me, but only because I had only one instance of this class in my app.
这对我有用,但这只是因为我的应用程序中只有这个类的一个实例。
#import <AVFoundation/AVFoundation.h>
@interface AVAudioPlayer (AstroAVAudioPlayer)
@property (nonatomic) BOOL redPilot;
@end
#import "AVAudioPlayer+AstroAVAudioPlayer.h"
@implementation AVAudioPlayer (AstroAVAudioPlayer)
BOOL _redPilot;
-(void) setRedPilot:(BOOL)redPilot
{
_redPilot = redPilot;
}
-(BOOL) redPilot
{
return _redPilot;
}
@end
回答by shokaveli
A solution that I found to this was to just give each object that you want flagged a unique tag.
我找到的一个解决方案是给每个你想要标记的对象一个唯一的标签。
I made a UILabel category to add custom fonts to all my labels but on some i wanted them to be bold so i did this ->
我创建了一个 UILabel 类别来为我的所有标签添加自定义字体,但在某些标签上我希望它们是粗体的,所以我这样做了 ->
- (void) layoutSubviews {
[super layoutSubviews];
[self addCustomFont];
}
- (void) addCustomFont {
if (self.tag == 22) {
[self setFont:[UIFont fontWithName:SEGOE_BOLD size:self.font.pointSize]];
}else{
[self setFont:[UIFont fontWithName:SEGOE_LIGHT size:self.font.pointSize]];
}
}