无法制作NSArray深层拷贝

时间:2013-09-03 22:07:40

标签: ios objective-c nsarray parse-platform deep-copy

我的应用上的用户可以选择过滤器来缩小项目范围。选择过滤器后,会发送NSNotification,将选定过滤器数组(NSString)传递给另一个视图控制器。

收到通知后,我可以从[notification userInfo]中提取数组。现在,我想要做的是将新过滤器与已经为用户保存的过滤器进行比较,以便仅在它们不同时才调用服务器。这是我的方法:

- (void)applyFilters:(NSNotification *)notification {

    NSArray *filters = [[notification userInfo] objectForKey:@"filters"];

    if (showMyItems) {

        if (![[NSSet setWithArray:filters] isEqualToSet:[NSSet setWithArray:[[PFUser currentUser] objectForKey:@"filtersMy"]]]) {

            [[PFUser currentUser] setObject:[NSArray arrayWithArray:filters] forKey:@"filtersMy"];
            [[PFUser currentUser] saveInBackground];
        }

    } else {

        if (![[NSSet setWithArray:filters] isEqualToSet:[NSSet setWithArray:[[PFUser currentUser] objectForKey:@"filters"]]]) {

            [[PFUser currentUser] setObject:[NSArray arrayWithArray:filters] forKey:@"filters"];
            [[PFUser currentUser] saveInBackground];
        }
    }
}

这里我比较的是NSSet而不是NSArray,因为对象/字符串的顺序并不重要。我尝试做的是创建一个新数组,并通过arrayWithArray:设置为用户的新过滤器。因此,当用户下次更改过滤器选择时,我希望新的filters数组与为用户保存的数组(我的if语句条件)不同。但是,当我同时使用NSLog(new和saved / fetched数组)时,它们完全相同!因此if条件永远不会过去。

我对此的唯一解释是[NSArray arrayWithArray:filters]仍以某种方式指向filters数组。

我甚至尝试过在SO和Apple上提出的[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:filters]],但结果是一样的。

有人可以发现我的问题吗?我没有选择和想法......

更新

我现在已经粘贴了完整的方法(上面)。更多背景:

  • 我使用的是同一UIViewController
  • 的两个实例
  • 在一个实例中,showMyItems设置为YES(因此只调用if语句的顶部)。在另一个例子中 - NO,因此只有下半部分被称为
  • 有趣的是,当showMyItemsNO时,我的代码按预期工作!但是当showMyItemsYES时,它不会......虽然代码相同。

有什么想法吗?

3 个答案:

答案 0 :(得分:0)

NSArray *temp = [[NSMutableArray alloc] initWithArray:filters copyItems:YES]; 

(以上适用于一级深拷贝)

对于深度复制,我到目前为止找到的最佳方法是

NSMutableArray *deepCopyArray = (NSMutableArray*)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)filters, kCFPropertyListMutableContainers));

答案 1 :(得分:0)

我已经测试了一些代码,但我不知道为什么你的If语句没有触发。以下是示例代码:

NSArray *newFilters = @[@"A",@"B",@"D"];
NSArray *oldFilters = [[NSUserDefaults standardUserDefaults] objectForKey:@"filters"];

if (![[NSSet setWithArray:newFilters] isEqualToSet:[NSSet setWithArray:oldFilters]]) {
    [[NSUserDefaults standardUserDefaults] setObject:newFilters forKey:@"filters"];
    [[NSUserDefaults standardUserDefaults] synchronize];
} else {
    NSLog(@"Not Equal");
}

此代码将相应地响应过滤器更改。我不确定为什么你在这里创建一个新数组[[PFUser currentUser] setObject:[NSArray arrayWithArray:filters] forKey:@"filters"];

答案 2 :(得分:0)

重写我以前的方法来解决我的问题,虽然老实说我并不完全明白为什么。

- (void)applyFilters:(NSNotification *)notification {

    NSArray *filters = [[notification userInfo] objectForKey:@"filters"];

    NSString *key = (myItems) ? @"filtersMy" : @"filters";

    if (![[NSSet setWithArray:filters] isEqualToSet:[NSSet setWithArray:[[PFUser currentUser] objectForKey:key]]]) {

        [[PFUser currentUser] setObject:[NSArray arrayWithArray:filters] forKey:key];
        [[PFUser currentUser] saveInBackground];

        [self setUpItemsArrayWithFilters:filters];
    }
}

我基本上只使用相同的代码一次,只使用不同的密钥,具体取决于当前活动的控制器。