编辑
以下“更简单”的代码按预期工作。请参阅下面的代码,并在评论中解释我的观察结果。
- (void) changeDictValue
{
//If the method just uses the line below, then calling changeDictValue has no impact on self.bcastSeqNumList
NSMutableDictionary *seqListToUpdate = [NSMutableDictionary dictionaryWithDictionary:self.bcastSeqNumList] ;
//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 ;
}
所以,看起来我下面的代码中存在一些错误(或者在调用 dictionaryWithDictionary 期间如何处理 NSSet 的一些特殊 Obj-C 逻辑导致与 missingSeqType 键关联的 NSSet 受到影响,即使我正在对从 self.bcastSeqNumList 派生的新字典进行操作。有什么线索吗?
结束编辑
我有一个表示序列号的 NSDictionary
。
1.一个键(lastContSeqType)代表最大的序列号X,这样我就收到了所有的序列号<=X
2. 一键(maxRcvdSeqType)代表我目前收到的最大序列号
3.一个key(missingSeqType)代表一组“缺失的序列号”
我有一个这样的字典用于“广播消息”,并且有一个这样的字典用于每个带有远端的单播消息。
当我从服务器获取存储的序列号列表时,我使用存储在我端的序列号列表和接收到的序列号列表来确定要检索的序列号。
当我执行以下代码行时,
在 getMissingSequenceNumsFromServerNSDictionary *) dict 的第一个实现中,一切正常,bcastSeqNumList
正在更新,lastContSeqType
更新为 4 并且 missingSeqType
为空。
在第二个实现中,我从 self.bcastSeqNumList
的内容创建一个新字典,然后操作这个“复制的”字典,我不希望 self.bcastSeqNumList
受方法内任何操作的影响。我看到 lastContSeqType
键不受影响,但 missingSeqType
键受到影响并变成一个空列表(即 NSNumber
对象@(4)正在被删除)。为什么会这样?
self.bcastSeqNumList= [@{@(lastContSeqType) : @(1), @(maxRcvdSeqType) : @(6), @(missingSeqType) : [NSMutableSet setWithObject(4)]
} mutableCopy];
NSLog(@"Bcast seq num list = %@",self.bcastSeqNumList) ;
NSMutableDictionary *rcvdDict= [@{@"currBroadcastSeqNumStart" : @(5), @"currBroadcastSeqNumEnd" : @(6)
} mutableCopy];
[self getMissingSequenceNumsFromServer:rcvdDict] ;
NSLog(@"Bcast seq num list = %@",self.bcastSeqNumList) ;
案例 1 实现
- (void) getMissingSequenceNumsFromServerNSDictionary *) dict
{
NSInteger serverStoreSeqStart=[dict[@"currBroadcastSeqNumStart"] integerValue] ;
NSInteger serverStoreSeqEnd=[dict[@"currBroadcastSeqNumEnd"] integerValue] ;
NSMutableDictionary *seqListToUpdate = self.bcastSeqNumList ;
NSInteger mySeq = [seqListToUpdate[@(lastContSeqType)] integerValue] ;
if(mySeq < serverStoreSeqStart-1)
{
//Ask for all stored messages in server
//[self getMessagesfromStart:serverStoreSeqStart toEnd:serverStoreSeqEnd] ;
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([seqListToUpdate objectForKey(missingSeqType)])
{
if([seqListToUpdate[@(missingSeqType)] containsObject:[NSNumber numberWithInteger:nextSeqToRemove]])
{
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
[seqListToUpdate[@(missingSeqType)] removeObject(nextSeqToRemove)] ;//
//If set is empty
if([seqListToUpdate[@(missingSeqType)] count] ==0)
{
//Nothing left in missing seq table. set it to nil and return
[seqListToUpdate removeObjectForKey(missingSeqType)] ;
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)] = [NSNumber numberWithInteger:serverStoreSeqStart-1] ;
if(seqListToUpdate[@(maxRcvdSeqType)] <= seqListToUpdate[@(lastContSeqType)])
{
seqListToUpdate[@(maxRcvdSeqType)] = seqListToUpdate[@(lastContSeqType)] ;
//Set to misisng seq num list = nil
}
else
{
//remove seqnums
}
}
else if (mySeq < serverStoreSeqEnd)
{
//[self getMessagesfromStart:mySeq+1 toEnd: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) ;
}
}
案例 2 实现
下面一行
seqListToUpdate = self.bcastSeqNumList ;
被下面的行替换,以便对 seqListToUpdate
的任何更改都不会影响 self.bcastSeqNumList
的内容
seqListToUpdate = [NSMutableDictionary dictionaryWithDictionary:self.bcastSeqNumList] ;
您必须进行深层复制。目前,您只是将引用复制到相同的对象。您还必须复制字典中引用的对象。
easiest way of doing a deep copy is using NSKeyedArchiver
归档和取消归档。
NSDictionary* deepCopy = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObjectriginalDict]];
关于ios - 如何在不更改原始内容的情况下操作 NSDictionary 内容的副本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34128112/
欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) | Powered by Discuz! X3.4 |