Z S*_*Z S 36 iphone objective-c
我正在尝试创建NSMutableDictionary的深层副本并将其分配给另一个NSMutableDictionary.字典包含一堆数组,每个数组包含名称,键是字母表(这些名称的第一个字母).因此字典中的一个条目是'A' - >'Adam','Apple'.这是我在书中看到的内容,但我不确定它是否有效:
- (NSMutableDictionary *) mutableDeepCopy
{
NSMutableDictionary * ret = [[NSMutableDictionary alloc] initWithCapacity: [self count]];
NSArray *keys = [self allKeys];
for (id key in keys)
{
id oneValue = [self valueForKey:key]; // should return the array
id oneCopy = nil;
if ([oneValue respondsToSelector: @selector(mutableDeepCopy)])
{
oneCopy = [oneValue mutableDeepCopy];
}
if ([oneValue respondsToSelector:@selector(mutableCopy)])
{
oneCopy = [oneValue mutableCopy];
}
if (oneCopy == nil) // not sure if this is needed
{
oneCopy = [oneValue copy];
}
[ret setValue:oneCopy forKey:key];
//[oneCopy release];
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
以下是我将如何调用此方法:
self.namesForAlphabets = [self.allNames mutableDeepCopy];
那可以吗?还是会导致泄漏?(假设我将self.namesForAlphabets声明为属性,并在dealloc中释放它).
Wev*_*vah 75
由于免费桥接,您还可以使用CoreFoundation功能CFPropertyListCreateDeepCopy:
NSMutableDictionary *mutableCopy = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)originalDictionary, kCFPropertyListMutableContainers);
Run Code Online (Sandbox Code Playgroud)
Tom*_*ing 11
假设阵列的所有元素都实现了NSCoding协议,您可以通过归档来执行深层复制,因为归档将保留对象的可变性.
像这样的东西:
id DeepCopyViaArchiving(id<NSCoding> anObject)
{
NSData* archivedData = [NSKeyedArchiver archivedDataWithRootObject:anObject];
return [[NSKeyedUnarchiver unarchiveObjectWithData:archivedData] retain];
}
Run Code Online (Sandbox Code Playgroud)
但这并不是特别有效.
重要提示:问题(以及我的代码)都处理了一个非常具体的案例,其中NSMutableDictionary 只包含字符串数组.这些解决方案不适用于更复杂的示例.有关更一般的案例解决方案,请参阅以下内容
这个具体案例的答案:
你的代码应该可行,但你肯定需要[oneCopy release].新词典将在您添加时保留复制的对象setValue:forKey,因此如果您不调用[oneCopy release],则所有这些对象将被保留两次.
一个好的经验法则:如果你alloc,retain或copy什么的,你也一定要release它.
注意:这里有一些示例代码仅适用于某些情况.这是有效的,因为您的NSMutableDictionary只包含字符串数组(不需要进一步深度复制):
- (NSMutableDictionary *)mutableDeepCopy
{
NSMutableDictionary * ret = [[NSMutableDictionary alloc]
initWithCapacity:[self count]];
NSMutableArray * array;
for (id key in [self allKeys])
{
array = [(NSArray *)[self objectForKey:key] mutableCopy];
[ret setValue:array forKey:key];
[array release];
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
我见过的另一种技术(它根本不是非常有效)是使用一个NSPropertyListSerialization对象来序列化你的字典,然后你对它进行反序列化,但指定你想要可变的叶子和容器.
NSString *errorString = nil;
NSData *binData =
[NSPropertyListSerialization dataFromPropertyList:self.allNames
format:NSPropertyListBinaryFormat_v1_0
errorString:&errorString];
if (errorString) {
// Something bad happened
[errorString release];
}
self.namesForAlphabets =
[NSPropertyListSerialization propertyListFromData:binData
mutabilityOption:NSPropertyListMutableContainersAndLeaves
format:NULL
errorDescription:&errorString];
if (errorString) {
// something bad happened
[errorString release];
}
Run Code Online (Sandbox Code Playgroud)
同样,这根本不是有效的.
尝试通过检查来找出答案respondToSelector(@selector(mutableCopy))不会给出所需的结果,因为所有NSObject基于 - 的对象都会响应此选择器(它是 的一部分NSObject)。相反,我们必须查询一个对象是否符合NSMutableCopying或至少符合NSCopying. 这是我根据已接受答案中提到的要点给出的答案:
为了NSDictionary:
@implementation NSDictionary (MutableDeepCopy)
// As seen here (in the comments): https://gist.github.com/yfujiki/1664847
- (NSMutableDictionary *)mutableDeepCopy
{
NSMutableDictionary *returnDict = [[NSMutableDictionary alloc] initWithCapacity:self.count];
NSArray *keys = [self allKeys];
for(id key in keys) {
id oneValue = [self objectForKey:key];
id oneCopy = nil;
if([oneValue respondsToSelector:@selector(mutableDeepCopy)]) {
oneCopy = [oneValue mutableDeepCopy];
} else if([oneValue conformsToProtocol:@protocol(NSMutableCopying)]) {
oneCopy = [oneValue mutableCopy];
} else if([oneValue conformsToProtocol:@protocol(NSCopying)]){
oneCopy = [oneValue copy];
} else {
oneCopy = oneValue;
}
[returnDict setValue:oneCopy forKey:key];
}
return returnDict;
}
@end
Run Code Online (Sandbox Code Playgroud)
为了NSArray:
@implementation NSArray (MutableDeepCopy)
- (NSMutableArray *)mutableDeepCopy
{
NSMutableArray *returnArray = [[NSMutableArray alloc] initWithCapacity:self.count];
for(id oneValue in self) {
id oneCopy = nil;
if([oneValue respondsToSelector:@selector(mutableDeepCopy)]) {
oneCopy = [oneValue mutableDeepCopy];
} else if([oneValue conformsToProtocol:@protocol(NSMutableCopying)]) {
oneCopy = [oneValue mutableCopy];
} else if([oneValue conformsToProtocol:@protocol(NSCopying)]){
oneCopy = [oneValue copy];
} else {
oneCopy = oneValue;
}
[returnArray addObject:oneCopy];
}
return returnArray;
}
@end
Run Code Online (Sandbox Code Playgroud)
两种方法都具有相同的内部复制或不复制逻辑,并且可以将其提取到单独的方法中,但为了清楚起见,我将其保留为这样。
| 归档时间: |
|
| 查看次数: |
27428 次 |
| 最近记录: |