1

A user on my app can select filters to narrow down items. Once filters are selected, an NSNotification is sent that passes an array of selected filters (NSStrings) to another view controller.

When I receive a notification, I can extract the array from [notification userInfo]. Now, what I want to do is to compare the new filters with those already saved for the user, so that I make a call to the server only if they are different. Here's my method:

- (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];
        }
    }
}

Here I'm comparing NSSets rather than NSArrays because the order of objects/strings is not important. What I try to do then is create a new array and set is as user's new filters via arrayWithArray:. So, when the next time the user changes filter selection, I expect that new filters array will be different from the one saved for the user (my if statement condition). However, when I NSLog both (new and saved/fetched arrays), they are exactly the same! And therefore the if condition never passes.

My only explanation of this is that the [NSArray arrayWithArray:filters] is somehow still pointing to filters array.

I even tried the [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:filters]] suggested on SO and by Apple, but the result is the same.

Can somebody please spot my problem? I'm out of options and ideas...

UPDATE:

I have now pasted the full method (above). A bit more background:

  • I am using two instances of the same UIViewController class
  • In one instance, showMyItems is set to YES (so only the top part of if statement is called). In another instance - NO, so only the lower part is called
  • What is interesting, when showMyItems is NO, my code works as expected! But when showMyItems is YES, it doesn't... Although the code is identical.

Any thoughts?

4

3 回答 3

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

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

对于深度复制,我到目前为止发现的最好方法是

NSMutableArray *deepCopyArray = (NSMutableArray*)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)filters, kCFPropertyListMutableContainers));
于 2013-09-03T22:26:58.790 回答
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"];

于 2013-09-03T22:35:12.803 回答
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];
    }
}

我基本上所做的只是使用相同的代码一次,根据当前活动的控制器只使用不同的键。

于 2013-09-21T17:30:04.137 回答