1

createcountなどの NSManagedObject のカテゴリを作成しました。以下を除いて、それらのすべての作品が見つかります

@interface NSManagedObject(ManagedObjectExtension) 
+ (id)findWithPredicate:(id)stringOrPredicate, ...;
@end

@implementation NSManagedObject(ManagedObjectUtilities)

+ (id)findWithPredicate:(id)stringOrPredicate, ... {
    NSFetchRequest *fetchRequest = [self allFetchRequest];
    if (stringOrPredicate) {
        NSPredicate *predicate;
        if ([stringOrPredicate isKindOfClass:[NSString class]]) {
            va_list variadicArguments;
            va_start(variadicArguments, stringOrPredicate);
            predicate = [NSPredicate predicateWithFormat:stringOrPredicate arguments:variadicArguments];
            va_end(variadicArguments);
        } else {
            predicate = (NSPredicate *)stringOrPredicate;
        }
        [fetchRequest setPredicate:predicate];
    }


    NSError *error;
    NSArray *results = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];

    if (error) {
        NSLog(@"%@", [error description]);
    }

    if ([results count] == 0) {
        return nil;
    } else if ([results count] == 1) {
        return [results objectAtIndex:0];
    } else {
        return results;
    }
}

@end

そしてこちらが結果

NSString *email = [NSString stringWithString:someTextField.text];
NSLog(@"%@", [User findWithPredicate:@"email == "%@", email]);
==> (null)
NSLog(@"%@", [User findWithPredicate:[NSString stringWithFormat:@"email == "%@", email]]);
==> "<User: 0x1d827e10> ..."

基本的に、このメソッドは、書式設定された文字列と引数の代わりに文字列を送信した場合にのみ機能します。このメソッド内で作成された述語を出力すると、これらは結果です

[User findWithPredicate:@"email == "%@", email];
==> email == "%@"
[User findWithPredicate:[NSString stringWithFormat:@"email == "%@", email]];
==> email == "tar.tw45@gmail.com"

何がこれを引き起こす可能性があるか考えていますか?コメントや提案は大歓迎です:)

4

1 に答える 1

2

質問のコードの引用符を忘れており(@kitschmasterがコメントで述べているように)、コードは実際には次のようになっていると思います。

NSString *email = @"tar.tw45@gmail.com";
// Case 1:
NSLog(@"%@", [User findWithPredicate:@"email == '%@'", email]);
// Case 2:
NSLog(@"%@", [User findWithPredicate:[NSString stringWithFormat:@"email == '%@'", email]]);

(1)の場合、ユーティリティメソッドは次の述語を作成します

[NSPredicate predicateWithFormat:@"email == '%@'", email];

この述語は、引用符が原因で逐語的な文字列を検索します。 "%@"引用符を削除した場合:

NSLog(@"%@", [User findWithPredicate:@"email == %@", email]);

その後、正しく動作します。

(2)の場合、ユーティリティメソッドは述語を作成します

[NSPredicate predicateWithFormat:@"email == 'tar.tw45@gmail.com'"];

すでにフォーマットされたクエリ文字列で呼び出されるためです。これは、この特定の場合に機能します。ただし、クエリ自体に引用符が含まれていると失敗します。例えば:

[User findWithPredicate:@"name == %@", @"a'b"]

正しく動作しますが

[User findWithPredicate:[NSString stringWithFormat:@"name == '%@'", @"a'b"]]

クラッシュします。述語を作成するときは、通常、の使用はstringWithFormat避けてください。

概要:最初のバージョンは、フォーマット文字列の引用符を省略した場合に正しく機能します。2番目のバージョンは使用しないでください。

于 2013-02-09T10:05:07.267 に答える