Ios @目标C中的动态特性

Ios @目标C中的动态特性,ios,objective-c,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 但当我运行时,我的应用程序崩溃了 当我

我试图在我的项目中实现一个动态属性 这是我的密码

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
但当我运行时,我的应用程序崩溃了

当我使用ivar时,出现了这个错误。

您的解决方案会导致递归,因为您没有在setter中使用
ivar
,所以会导致崩溃,请尝试以下方法:

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

这个答案:很好地解释了
@synthesis
@dynamic
之间的区别。通常,如果您正在委派实现访问器(get、set)的任务,则使用
@dynamic
。在我看来,你可能想在这里使用@synthesis。但是使用现代的objective c,您甚至不需要指定,iVar将自动为您创建

i、 e:

MyClass.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface MyClass : NSObject
@property (strong, nonatomic) NSString *name;
@end

NS_ASSUME_NONNULL_END

属性只是两个方法的组合: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
  • 合成吸气剂和塞特剂
  • 自动合成吸气剂和沉降剂
  • 编写自定义getter和setter
  • 使用
    @dynamic
    避免编译时警告,因为您打算执行运行时魔术。(真的,这不是你想做的,因为你需要先了解基本知识。)
参考iVar手动编写getter和setter 在实施过程中,

@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
自动合成吸气剂和沉降剂 实际上,您只需要使用“自动合成”

这就是说,

  • 如果你只是声明一个属性
  • 不要调用
    @synthetic
    @dynamic
  • 不要实现任何自定义getter和setter
上面的代码将只创建一个名为
\u name
的iVar和一个与第一个示例中的完全相同的getter和setter

这意味着前两部分和此部分是等效的,因为它们生成相同的代码

编写自定义getter和setter 这就是术语“动态属性”的真正含义。例如,您可能希望名称始终为大写。所以你可以写一个这样的属性

@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
——别担心,这只是一个注释。这是一个真实的注释,因为
大写字符串
永远不会相同,它将始终是原始字符串的副本。)

这可能是唯一真正有趣的案例例如,UIKit一直使用这种属性,例如
UILabel
text
属性就是这样的动态属性。它不仅设置了一些iVar,还确保了屏幕上的可见文本也发生了变化

@dynamic
属性 他们真的很难做到正确,而且大多数时候他们都不值得费心


注意:我简化了一些内容,并省略了只有在使用objc运行时检查API时才能检测到的细节

为什么要在这里使用
@dynamic
@dynamic
用于在编译时不提供实现,但稍后通过Objective-C runtime magic添加实现的属性。既然你在这里提供了一个二传手,显然不是这样,所以。。。你想做什么?这只是一个@charlessrstkab的例子,但是一个什么的例子?你想做什么?我同意在这里使用
@dynamic
是无用的和误导性的。但这是一次非手术,不会造成车祸。我看到堆栈溢出是因为无限递归。。请不要因为“不清楚你在问什么”而投票——问题非常清楚:OP不理解(1)属性、访问器和IVAR之间的关系,(2)如何声明IVAR,以及(3)动态
@dynamic
的含义。他(4)将“动态属性”与
@dynamic
属性混为一谈,这其实不是一回事,尽管说话时听起来是一样的。也许我可以在问题结束前写一个答案。@JosuéH。那是因为你没有申报ivar。
@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
@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