我正在尝试在我的项目中实现动态属性 这是我的代码。
MyClass.h
@interface MyClass : UIView
@property (strong, nonatomic) NSString *name;
@end
MyClass.m
@implementation MyClass
@dynamic name;
-(void)setName:(NSString *)name{
self.name = name;
}
@end
但是当我运行我的应用程序时崩溃了。
答案 0 :(得分:3)
这个StackOverflow答案:https://stackoverflow.com/a/1160545/7833793很好地解释了@synthesize
和@dynamic
之间的区别。如果要委派实现访问器(获取,设置)的任务,通常使用@dynamic
。在我看来,您似乎想在这里使用@synthesize。但是对于现代目标c,您甚至无需指定,iVar就会自动为您创建。
即:
MyClass.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MyClass : NSObject
@property (strong, nonatomic) NSString *name;
@end
NS_ASSUME_NONNULL_END
MyClass.m
#import "MyClass.h"
@implementation MyClass
- (void)setName:(NSString *)name {
_name = name;
}
@end
答案 1 :(得分:2)
属性只是两个方法的捆绑:getter和setter。所以,当你写
@property (strong, nonatomic) NSString *name;
你真正在说的是
- (NSString *)name;
- (void)setName:(NSString *)name;
此后,每次编译器遇到obj.name
形式的表达式时,都会将其转换为[obj name]
。并且每次您看到类似obj.name = @"hello";
的语句时,编译器都会将其转换为[obj setName:@"hello"]
。
接下来的一件事是您必须确保该属性的行为正确。您有很多选择:
@dynamic
避免编译时警告,因为您打算执行运行时魔术。 (确实,这不是您想要做的,因为您需要首先了解基础知识。)@interface MyClass : UIView {
NSString *_name;
}
@property (strong, nonatomic) NSString *name;
@end
以及实施中
@implementation MyClass
- (NSString *)name {
return _name;
}
- (void)setName:(NSString *)name {
_name = name;
}
@end
最后一部分基本上等于
@interface MyClass : UIView {
NSString *_name;
}
@property (strong, nonatomic) NSString *name;
@end
@implementation MyClass
@synthesize name = _name;
@end
在实践中,您只需要使用“自动合成”即可。
@interface MyClass : UIView
@property (strong, nonatomic) NSString *name;
@end
@implementation MyClass
@end
这是
@synthesize
或@dynamic
上面的代码将只创建一个名为_name
的iVar,以及一个与第一个示例中的外观完全相同的吸气剂和吸气剂。
这意味着前两个部分与本部分相同,因为它们产生相同的代码。
这就是术语“动态特性”的真正含义。例如,您可能希望名称始终为大写。因此,您可以编写这样的属性。
@interface MyClass : UIView {
NSString *_name;
}
@property (copy, nonatomic) NSString *name;
@end
@implementation MyClass
- (NSString *)name {
return _name;
}
- (void)setName:(NSString *)name {
_name = [name uppercaseString];
}
@end
(在上面的代码中,我将strong
更改为copy
-不用担心,这只是一条注释。这是一个真实的注释,因为uppercaseString
永远不会一样,它将始终是原始文档的副本。)
这也许是唯一真正有趣的情况!例如,UIKit一直使用这种属性,例如text
的{{1}}属性是这样的动态属性。它不仅设置了一些iVar,而且还确保了屏幕上的可见文本也发生了变化。
UILabel
属性他们真的很难正确,而且大多数时候他们都不值得麻烦恕我直言。
注意:我简化了一些事情,并省略了只有在使用objc运行时检查API时才能检测到的细节
答案 2 :(得分:1)
您的解决方案会导致递归,因为您未在setter中使用ivar
,所以您会崩溃,请尝试以下方法:
-(void)setName:(NSString *)name{
_name = name;
}