0

プログラムで数値を更新しようとしているcoredataプロジェクトがあります。CoreDataからオブジェクトを取得し、それを配列に格納しています。

次に、その配列をループして、現在のユーザーのIPがデータベースに存在するかどうかを確認し、その特定の配列にアクセスされた回数を更新しようとしています。

問題は、ループ配列内の現在のオブジェクトだけでなく、すべてのオブジェクトを更新していることです。

まず、次のようなコアデータから情報を取得します。

- (void)fetchRecords {

    // Define our table/entity to use
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"IPAddr" inManagedObjectContext:managedObjectContext];

    // Setup the fetch request
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];

    // Define how we will sort the records
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"ipDate" ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    [request setSortDescriptors:sortDescriptors];


    // Fetch the records and handle an error
    NSError *error;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];

    if (!mutableFetchResults) {
        // Handle the error.
        // This is a serious error and should advise the user to restart the application
    }

    // Save our fetched data to an array
    [self setIpArray: mutableFetchResults];

}

現在、フェッチされた結果に現在のユーザーIPが存在するかどうかを調べ、存在する場合は、アクセスされた回数を更新しようとしています。

// see if the ip is present and update if necessary
-(void)ipPresent {
    NSString * theCurrentIP = [self getGlobalIPAddress];
    for (IPAddr *allips in ipArray)
    {
        if ([allips.ipNum isEqualToString:theCurrentIP]) {
            NSLog(@"The IP %@ was found.", theCurrentIP);

            // update the ip

            NSError *error = nil;

            NSNumber *ipToUpdate = allips.ipAccess;

            NSNumber *addIpAccess = [[NSNumber alloc] initWithInt:1];
            NSNumber *updateIpAddress = [NSNumber numberWithFloat:([ipToUpdate floatValue] + [addIpAccess floatValue])];

            [self.ipArray setValue:updateIpAddress forKey:@"ipAccess"];


            if ([self.managedObjectContext save:&error]) {  // write to database
            NSLog(@"The IP Was Updated from %@ to %@", ipToUpdate, updateIpAddress);
            } else if (![self.managedObjectContext save:&error]) {
                NSLog(@"failed with error: %@", error);
            }
            break;

        } else {
            NSLog(@"The IP %@ was NOT found.", theCurrentIP);

        }
    }
} 

問題は次の行にあると確信しています。

[self.ipArray setValue:updateIpAddress forKey:@"ipAccess"];

繰り返しますが、現在のループ内のエンティティだけでなく、すべてのエンティティを更新しています。

4

1 に答える 1

2

それはそう。間違った方法を使用しています。 self.ipArrayですNSMutableArray

方法

- (void)setValue:(id)value forKey:(NSString *)key

Key-Valueコーディング(Core Dataオブジェクトで機能する)に使用されますが、配列に適用すると、配列の各エントリでsetValue:forKey:が呼び出されます。

setValue:forKeyこれで、プロパティが明らかにKVCに準拠しているため、単一の配列要素を呼び出すこともできることがわかります。allipsそうしないと、設定されている値が表示されず、別の問題が発生します。

プロパティを割り当てることもできることに注意してください...

allips.ipAccess = updateIpAddress;

編集

申し訳ありませんが、おそらく読み取り速度が遅いはずです...可変配列を使用する必要がないことを理解していますか?実際に配列を変更するのではなく、配列内の要素だけを変更します。不変のコレクションとは、コレクションの内容を変更できないことを意味しますが、オブジェクトへのポインターがある場合、そのオブジェクトが不変でない限り、そのプロパティを変更できます。

したがって、Fooオブジェクトの不変の配列がある場合は、これを行うことができます...

for (Foo *foo in myImmutableArray) {
    Bar *bar = [self getSomeNewBar];
    [foo setBar:bar];

    // If Foo is KVC compliant, you can do this too...
    [foo setValue:bar for Key:@"bar"];
}

ただし、配列を呼び出すsetValue:forKeyと、配列の要素ごとに呼び出されます。setValue:forKeyこれは実際には不変のNSArrayで宣言されていることに注意してください。

編集

そのコメントは読みづらかった。

コアデータオブジェクトは単なる別のオブジェクトです。サブクラス化して、属性のプロパティを提供したようです。交換するだけ

[self.ipArray setValue:updateIpAddress forKey:@"ipAccess"];

[allips setValue:updateIpAddress forKey:@"ipAccess"];

また

allips.ipAccess = updateIpAddress;

「ipAccess」という名前の読み取り/書き込みプロパティを持つオブジェクトと同様に、どちらもコアデータオブジェクトを変更する必要があります

もちろん、私がそれを再び間違って読んでいないと仮定すると...そしてallipsはあなたのコアデータオブジェクトです...

于 2012-08-18T06:08:23.107 に答える