目标C中的@dynamic属性

时间:2018-09-17 22:08:14

标签: ios objective-c

我正在尝试在我的项目中实现动态属性 这是我的代码。

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

但是当我运行我的应用程序时崩溃了。

enter image description here

当我使用ivar时出现此错误。 enter image description here

3 个答案:

答案 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"]

接下来的一件事是您必须确保该属性的行为正确。您有很多选择:

  • 参考iVar手动编写吸气剂和设置器
  • 合成吸气剂和设定剂
  • 自动合成getter和setter
  • 编写自定义获取和设置方法
  • 使用@dynamic避免编译时警告,因为您打算执行运行时魔术。 (确实,这不是您想要做的,因为您需要首先了解基础知识。)

参考iVar手动编写吸气剂和吸气剂

@interface MyClass : UIView {
    NSString *_name;
}

@property (strong, nonatomic) NSString *name;

@end

以及实施中

@implementation MyClass

- (NSString *)name {
    return _name;
}
- (void)setName:(NSString *)name {
    _name = name;
}

@end

合成getter和setter

最后一部分基本上等于

@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
  • 不要实现任何自定义的getter和setter

上面的代码将只创建一个名为_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;
}