• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ios - 用于创建可变副本的 Objective-C 模式

[复制链接]
菜鸟教程小白 发表于 2022-12-12 19:18:13 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我有许多“模型”对象,它们的属性被定义为“只读”并在各个组件之间共享。

在某些情况下,我需要创建对象的本地可变副本(将它们用于本地可变状态)

我宁愿不实现 NSMutableCopy 协议(protocol),因为对象在创建后应该是不可变的。修改后的对象可以在复制+变异操作后“传递”。

是否有建议的机制,或者我应该只实现一个接收“更改”参数的构造函数?

例如,将 JSON 解析为原生类型的对象:

@interface ImmutableObject : NSObject
// various "readonly" properties
...
-(instancetype)initWithJSONNSDictionary *)jsonDictionary;

@property (nonatomic, readonly) MyClass1 *prop1;
@property (nonatomic, readonly) MyClass2 *prop2;
...
@property (nonatomic, readonly) NSArray<MyClass100 *>  *prop100;

@end

@implementation 
-(instancetype)initWithJSONNSDictionary *)jsonDictionary {
  self = [super init];
  [self parseDictionaryToNative:jsonDictionary];
  return self;
}
@end

代码中的某处:

ImmutableObject *mutated = [immutableObject mutableCopy]; // best way to accomplish this?
// change some values...
mutated.prop1 = ... // change the value to something new

self.state = [mutated copy]; // save the new object



Best Answer-推荐答案


@spinalwrap 是正确的,但在这种情况下,没有理由在存储之前创建额外的副本。 NSMutableArrayNSArray 的子类,因此可以在任何可以使用 NSArray 的地方使用(这很常见)。你的也一样。在您的特定情况下,您可能会这样做:

MutableObject *mutated = [immutableObject mutableCopy]; // create an instance of MutableObject

mutated.prop1 = ... // change the value to something new

self.state = mutated; // Since `state` is an immutable type, 
                      // attempts to mutate this later will be compiler errors

这是安全的,因为您知道此代码块是唯一引用对象可变版本的代码块(因为您在此处创建了它)。

也就是说,一旦您创建了一个可变子类,您现在需要考虑传递给您的任何 ImmutableObject 实际上可能是一个 MutableObject 的可能性,因此制作防御性副本(就像使用 NSArrayNSString 等一样)例如:

- (void)cacheObjectImmutableObject *)object {
    // Need to copy here because object might really be a MutableObject
    [self.cache addObject:[object copy]];
}

通过在 ImmutableObjectreturn self 上实现 copy 并在 copy 上实现这一点相当有效code>MutableObject 作为一个实际的副本,通常是这样的:

ImmutableObject.m

- (ImmutableObject *)copy {
    return self;
}

MutableObject.m

// as in spinalwrap's example
- (MutableObject *)mutableCopy {
    MutableObject *instance = [MutableObject new];
    instance.prop1 = [self.prop1 copy]; // depends what you want here and what kind of class the properties are... do you need a deep copy? that might be a bit more work.
    // etc...
    return instance;
}

// No need to duplicate code here. Just declare it immutable; 
// no one else has a pointer to it
- (ImmutableObject *)copy {
    return (ImmutableObject *)[self mutableCopy];
}

因此,如果对象已经是不可变的,则副本几乎是免费的。我说“相当有效”,因为它仍然会导致一些不必要的可变对象副本,这些副本永远不会发生变异。 Swift 的值类型的写时复制系统是专门为处理 ObjC 中的这个问题而创建的。但以上是 ObjC 中常见的模式。

关于ios - 用于创建可变副本的 Objective-C 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36387121/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap