ios - 如何在不更改原始内容的情况下操作 NSDictionary 内容的副本
<p><p><strong>编辑</strong></p>
<p>以下“更简单”的代码按预期工作。请参阅下面的代码,并在评论中解释我的观察结果。 </p>
<pre><code>- (void) changeDictValue
{
//If the method just uses the line below, then calling changeDictValue has no impact on self.bcastSeqNumList
NSMutableDictionary *seqListToUpdate = ;
//But if it instead uses the line below, calling changeDictValue does change self.bcastSeqNumList
NSMutableDictionary *seqListToUpdate = self.bcastSeqNumList ;
seqListToUpdate[@(lastContSeqType)]=@(0) ;
seqListToUpdate[@(maxRcvdSeqType)]=@(1) ;
seqListToUpdate[@(missingSeqType)]=nil ;
}
</code></pre>
<p>所以,看起来我下面的代码中存在一些错误(或者在调用 dictionaryWithDictionary 期间如何处理 NSSet 的一些特殊 Obj-C 逻辑:)导致与 missingSeqType 键关联的 NSSet 受到影响,即使我正在对从 self.bcastSeqNumList 派生的新字典进行操作。有什么线索吗?</p>
<p><strong>结束编辑</strong></p>
<p>我有一个表示序列号的 <code>NSDictionary</code>。<br/>
1.一个键(lastContSeqType)代表最大的序列号X,这样我就收到了所有的序列号<=X
2. 一键(maxRcvdSeqType)代表我目前收到的最大序列号
3.一个key(missingSeqType)代表一组“缺失的序列号”</p>
<p>我有一个这样的字典用于“广播消息”,并且有一个这样的字典用于每个带有远端的单播消息。</p>
<p>当我从服务器获取存储的序列号列表时,我使用存储在我端的序列号列表和接收到的序列号列表来确定要检索的序列号。</p>
<p>当我执行以下代码行时,</p>
<p>在 <em>getMissingSequenceNumsFromServer:(NSDictionary *) dict</em> 的第一个实现中,一切正常,<code>bcastSeqNumList</code> 正在更新,<code>lastContSeqType</code>更新为 4 并且 <code>missingSeqType</code> 为空。 </p>
<p>在第二个实现中,我从 self.<code>bcastSeqNumList</code> 的内容创建一个新字典,然后操作这个“复制的”字典,我不希望 self.<code>bcastSeqNumList</code> 受方法内任何操作的影响。我看到 <code>lastContSeqType</code> 键不受影响,但 <code>missingSeqType</code> 键受到影响并变成一个空列表(即 <code>NSNumber</code> 对象@(4)正在被删除)。为什么会这样?</p>
<pre><code>self.bcastSeqNumList= [@{@(lastContSeqType) : @(1), @(maxRcvdSeqType) : @(6), @(missingSeqType) :
} mutableCopy];
NSLog(@"Bcast seq num list = %@",self.bcastSeqNumList) ;
NSMutableDictionary *rcvdDict= [@{@"currBroadcastSeqNumStart" : @(5), @"currBroadcastSeqNumEnd" : @(6)
} mutableCopy];
;
NSLog(@"Bcast seq num list = %@",self.bcastSeqNumList) ;
</code></pre>
<p><strong>案例 1 实现</strong></p>
<pre><code>- (void) getMissingSequenceNumsFromServer:(NSDictionary *) dict
{
NSInteger serverStoreSeqStart= integerValue] ;
NSInteger serverStoreSeqEnd= integerValue] ;
NSMutableDictionary *seqListToUpdate = self.bcastSeqNumList ;
NSInteger mySeq = integerValue] ;
if(mySeq < serverStoreSeqStart-1)
{
//Ask for all stored messages in server
// ;
NSLog(@"Getting messages from %ld and to %ld",serverStoreSeqStart,serverStoreSeqEnd) ;
NSLog(@"Never received seq nums %ld to %ld",mySeq+1,serverStoreSeqStart-1) ;
NSInteger nextSeqToRemove ;
for(nextSeqToRemove=mySeq+1;nextSeqToRemove<=serverStoreSeqStart-1;nextSeqToRemove++)
{
if()
{
if( containsObject:])
{
NSLog(@"SeqNum %ld is in missing seq num list and being removed since we got server seq %ld > than this",(long)nextSeqToRemove,(long)serverStoreSeqStart) ;
//Remove it
removeObject:@(nextSeqToRemove)] ;//
//If set is empty
if( count] ==0)
{
//Nothing left in missing seq table. set it to nil and return
;
seqListToUpdate[@(lastContSeqType)]=seqListToUpdate[@(maxRcvdSeqType)] ;
NSLog(@"Missing seq num list empty.Setting last contig to max = %@",seqListToUpdate[@(lastContSeqType)]) ;
break ;
}
}
}
else
{
//mising Seq Type has no elements, nothing to remove
break ;
}
}
//At the end..if serverSeqToStore >= maxSeq, then lastCOnt=maxSeq and missing seq empty.
//Else...if missing seq Empty, then
seqListToUpdate[@(lastContSeqType)] = ;
if(seqListToUpdate[@(maxRcvdSeqType)] <= seqListToUpdate[@(lastContSeqType)])
{
seqListToUpdate[@(maxRcvdSeqType)] = seqListToUpdate[@(lastContSeqType)] ;
//Set to misisng seq num list = nil
}
else
{
//remove seqnums
}
}
else if (mySeq < serverStoreSeqEnd)
{
// ;
NSLog(@"Getting messages from %ld and to %ld",mySeq+1,serverStoreSeqEnd) ;
}
else if (mySeq > serverStoreSeqEnd)
{
NSLog(@"My stored sequence number %ld exceeds the max stored at server %ld",(long)mySeq,(long)serverStoreSeqEnd) ;
}
}
</code></pre>
<p><strong>案例 2 实现</strong></p>
<p>下面一行</p>
<pre><code> seqListToUpdate = self.bcastSeqNumList ;
</code></pre>
<p>被下面的行替换,以便对 <code>seqListToUpdate</code> 的任何更改都不会影响 <code>self.bcastSeqNumList</code> 的内容 </p>
<pre><code> seqListToUpdate = ;
</code></pre></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>您必须进行深层复制。目前,您只是将引用复制到相同的对象。您还必须复制字典中引用的对象。</p>
<p><a href="https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Collections/Articles/Copying.html#//apple_ref/doc/uid/TP40010162-SW3" rel="noreferrer noopener nofollow">easiest way of doing a deep copy is using <code>NSKeyedArchiver</code></a>归档和取消归档。</p>
<pre><code>NSDictionary* deepCopy = [NSKeyedUnarchiver unarchiveObjectWithData:
];
</code></pre></p>
<p style="font-size: 20px;">关于ios - 如何在不更改原始内容的情况下操作 NSDictionary 内容的副本,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/34128112/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/34128112/
</a>
</p>
页:
[1]