1

私のアプリのユーザーはフィルターを選択してアイテムを絞り込むことができます。フィルターが選択されると、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];
        }
    }
}

オブジェクト/文字列の順序は重要ではないため、ここではNSSets ではなくs を比較しています。NSArray私がやろうとしているのは、新しい配列を作成し、arrayWithArray:. そのため、次にユーザーがフィルターの選択を変更したときに、新しいfilters配列がユーザー用に保存されたものとは異なることが予想されます (私の if ステートメントの条件)。ただし、両方 (新しい配列と保存/フェッチされた配列) を NSLog すると、それらはまったく同じです! したがって、if 条件は決して通過しません。

これについての私の唯一の説明は、何らかの形でまだ配列[NSArray arrayWithArray:filters]を指しているということです。filters

[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:filters]]SO と Appleの提案を試してみましたが、結果は同じです。

誰かが私の問題を見つけてもらえますか? 私は選択肢とアイデアが不足しています...

更新

完全なメソッド (上記) を貼り付けました。もう少し背景:

  • 同じUIViewControllerクラスの 2 つのインスタンスを使用しています
  • あるインスタンスでshowMyItemsは、に設定されます (そのため、ステートメントYESの上部のみが呼び出されます)。if別のインスタンスでは - NO、したがって、下部のみが呼び出されます
  • 興味深いのshowMyItemsNO、私のコードが期待どおりに動作することです! しかし、showMyItemsYESの場合、そうではありません... コードは同じですが。

何かご意見は?

4

3 に答える 3

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 に答える
0
NSArray *temp = [[NSMutableArray alloc] initWithArray:filters copyItems:YES]; 

(上記は 1 レベルの深さのコピーで機能します)

ディープコピーの場合、これまでに見つけた最良の方法は

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 に答える