菜鸟教程小白 发表于 2022-12-12 19:18:13

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


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

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

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

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

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

<pre><code>@interface ImmutableObject : NSObject
// various &#34;readonly&#34; properties
...
-(instancetype)initWithJSON:(NSDictionary *)jsonDictionary;

@property (nonatomic, readonly) MyClass1 *prop1;
@property (nonatomic, readonly) MyClass2 *prop2;
...
@property (nonatomic, readonly) NSArray&lt;MyClass100 *&gt;*prop100;

@end

@implementation
-(instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = ;
;
return self;
}
@end
</code></pre>

<p>代码中的某处:</p>

<pre><code>ImmutableObject *mutated = ; // best way to accomplish this?
// change some values...
mutated.prop1 = ... // change the value to something new

self.state = ; // save the new object
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>@spinalwrap 是正确的,但在这种情况下,没有理由在存储之前创建额外的副本。 <code>NSMutableArray</code> 是 <code>NSArray</code> 的子类,因此可以在任何可以使用 <code>NSArray</code> 的地方使用(这很常见)。你的也一样。在您的特定情况下,您可能会这样做:</p>

<pre><code>MutableObject *mutated = ; // 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
</code></pre>

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

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

<pre><code>- (void)cacheObject:(ImmutableObject *)object {
    // Need to copy here because object might really be a MutableObject
    ];
}
</code></pre>

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

<p><em>ImmutableObject.m</em></p>

<pre><code>- (ImmutableObject *)copy {
    return self;
}
</code></pre>

<p><em>MutableObject.m</em></p>

<pre><code>// as in spinalwrap&#39;s example
- (MutableObject *)mutableCopy {
    MutableObject *instance = ;
    instance.prop1 = ; // 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 *);
}
</code></pre>

<p>因此,如果对象已经是不可变的,则副本几乎是免费的。我说“相当有效”,因为它仍然会导致一些不必要的可变对象副本,这些副本永远不会发生变异。 Swift 的值类型的写时复制系统是专门为处理 ObjC 中的这个问题而创建的。但以上是 ObjC 中常见的模式。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 用于创建可变副本的 Objective-C 模式,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/36387121/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/36387121/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 用于创建可变副本的 Objective-C 模式