0

更新:まだ良い方法があるかもしれませんが、答えを見つけました-以下に追加された答えを参照してください。


Spotlight インポーターは、アイテムがアクセスされた日付の配列であるメタデータをインポートします。次のようになります。

kMDItemAccessedDates               = (
    "2012-06-18 07:00:00 +0000",
    "2013-01-10 08:00:00 +0000",
    "2013-01-15 08:00:00 +0000"
)

ユーザーが入力した特定の日付にアクセスされたこれらのファイルのいずれかを照会したいのですが、これを行うための正しい構文が見つかりません。できるかどうか疑問...

最初の問題は、ユーザーが日時ではなく日を表す日付を入力することです。

その日に当たる日付を検索する必要があるように思えたので、論理的には:ADATE >= user_day_start && ADATE <= user_day_end

現在、メタデータには日付の配列があるため、これらの日付のいずれかが user_date の日付内にある場合は、それを一致させたいと考えています。

これがうまくいったらいいですね:

NSDate * date = [NSDate dateWithNaturalLanguageString: inWhenString];
NSDate * endDate = [NSDate dateWithTimeInterval: 86400 sinceDate: date];

predicate = [NSPredicate predicateWithFormat: 
              @"kMDItemAccessedDates between {%@, %@}", date, endDate];

しかし、それは例外をスローします:

Exception detected while handling key input.
2013-01-16 03:12:57.517 Chatty[96974:403] Unknown type of NSComparisonPredicate 
  given to NSMetadataQuery 
  (kMDItemAccessedDates BETWEEN {CAST(379540800.000000, "NSDate"),
  CAST(379627200.000000, "NSDate")}) 

配列ではなく単一の日付に対してのみ機能するようです。次のようにフォーマット文字列に「ANY」を追加して"ANY kMDItemAccessedDates between {%@, %@}"も、例外がスローされ、役に立ちませんでした。

これを試してみましたが、例外はスローされていませんが、実際には機能していません:

NSPredicate *p1 = [NSPredicate predicateWithFormat: @"kMDItemAccessedDates >= %@", date ];
NSPredicate *p2 = [NSPredicate predicateWithFormat: @"kMDItemAccessedDates <= %@", endDate ];
predicate = [NSCompoundPredicate andPredicateWithSubpredicates: [NSArray arrayWithObjects: p1, p2, nil]];

誰かがこれを機能させる方法についてアイデアを持っているかどうか疑問に思っています...またはそれが不可能であることを知っています(それらをすべて取得してからメモリ内でフィルタを実行する必要があるなど)。そうでないことを本当に願っています-長いリストになる可能性があります!)。

4

2 に答える 2

1

それで、さらに数時間インターネット検索結果を掘り下げて試してみると、これはうまくいきました。

NSDate * userDate = [NSDate dateWithNaturalLanguageString: inWhenString];
NSDateComponents * userDateComponents = [[NSCalendar currentCalendar] components: NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate: userDate];
NSDate * dayDate = [[NSCalendar currentCalendar] dateFromComponents: userDateComponents];
dNSLog(@"date %@", dayDate );
NSString * formatStr = [NSDateFormatter dateFormatFromTemplate: @"yyyy-MM-dd" options: 0 locale: nil];
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat: formatStr];

NSString * dayStr = [formatter stringFromDate: dayDate];
dayStr = [dayStr stringByAppendingString: @"*"];
dNSLog(@"dayString: %@", dayStr );
NSPredicate *p1 = [NSPredicate predicateWithFormat: @"%K >= CAST(%f, \"NSDate\")", @"kMDItemAccessedDates", [dayDate timeIntervalSinceReferenceDate] ];
NSPredicate *p2 = [NSPredicate predicateWithFormat: @"%K <= CAST(%f, \"NSDate\")", @"kMDItemAccessedDates", [dayDate timeIntervalSinceReferenceDate] + 86400.0f ];
predicate = [NSCompoundPredicate andPredicateWithSubpredicates: @[p1, p2]];

このアプローチ全体には (アプリがこの日付の配列を更新する方法に基づいて) 他の問題がある可能性があり、別のことを完全に行う必要がある場合がありますが、これは、アクセスされたアイテムのみを取得する方法に関する最初の質問に答えているようです。特定の日。

鍵はCAST(%f, \"NSDate\")私が信じるものでした。

まだもっと良い方法があるかもしれませんが、他の誰かが手がかりを探している場合に備えて、これをここに置くと思いました.

于 2013-01-17T06:48:38.667 に答える
0

OK、これはあなたが望むアプローチだと思います。あなたのケースのような文字列の配列である kMDItemContentTypeTree 属性を見て、ファイルのフォルダーでこれをテストしました。基本的に、BEGINSWITH 検索を作成すると、その配列の値が検索されます。

BEGINSWITH 検索は、検索語の末尾に「*」が追加されていることを除いて、LIKE 検索です。私の考えは、ユーザー入力の日付を取得し、他の投稿で示した年/月/日を取得する手法を使用して、「YYYY-MM-DD」の形式で searchString を作成することです。次に、それらの値からその形式の文字列を作成します。

これで、述語を作成し、userDateString から次のようにクエリを開始できます。%K を使用して kMDItemAccessedDates プロパティを挿入したことに気付くでしょう。

NSString* userDateString = @"2013-01-15";

NSString* queryKeyString = @"kMDItemAccessedDates";
NSString* searchDate = [userDateString stringByAppendingString:@"*"];
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"%K like %@", queryKeyString, searchDate];

// folderQuery is your NSMetadataQuery
[folderQuery setSearchScopes:[NSArray arrayWithObject:folderPath]]; // the folder you want to search
[folderQuery setPredicate:predicate];
[folderQuery startQuery];
于 2013-01-16T15:58:01.590 に答える