Mac Spotlight-API: как искать сообщения электронной почты в полях «Кому», «От» или «Тема»

На данный момент у меня есть код Spotlight-API, который ищет в теле письма. Я использую NSMetadataQuery и создаю предикат для "kMDItemTextContent like[c] %@". Это отлично работает, когда запрошенный «поисковый запрос» находится в теле письма.

В приложении Spotlight (значок лупы в правом верхнем углу), если я введу «to: john», я получу список электронных писем, в которых поле «to» содержит слово «john» (например, часть некоторого адреса электронной почты [email protected]).

Я попытался добиться этого с помощью [NSCompoundPredicate orPredicateWithSubpredicates:], добавив дополнительные предикаты типа "kMDItemRecipients", "kMDItemRecipientEmailAddresses", "kMDItemAuthors", "kMDItemAuthorEmailAddresses" и "kMDItemSubject". К сожалению, это не возвращает желаемые электронные письма.

Кто-нибудь знает, как этого добиться с помощью Spotlight-API?

Ниже мой код для этого:

NSString *predicateFormat = @"kMDItemTextContent like[c] %@";
NSPredicate *predicateToRun = [NSPredicate predicateWithFormat:predicateFormat, self.searchKey];

NSString *predicateFormat1 = @"kMDItemTitle like[c] %@";
NSPredicate *predicateToRun1 = [NSPredicate predicateWithFormat:predicateFormat1, self.searchKey];

NSString *predicateFormat2 = @"kMDItemAuthorEmailAddresses like[c] %@";
NSPredicate *predicateToRun2 = [NSPredicate predicateWithFormat:predicateFormat2, self.searchKey];

NSString *predicateFormat3 = @"kMDItemAuthors like[c] %@";
NSPredicate *predicateToRun3 = [NSPredicate predicateWithFormat:predicateFormat3, self.searchKey];

NSString *predicateFormat4 = @"kMDItemRecipientEmailAddresses like[c] %@";
NSPredicate *predicateToRun4 = [NSPredicate predicateWithFormat:predicateFormat4, self.searchKey];

NSString *predicateFormat5 = @"kMDItemRecipients like[c] %@";
NSPredicate *predicateToRun5 = [NSPredicate predicateWithFormat:predicateFormat5, self.searchKey];

NSString *predicateFormat6 = @"kMDItemSubject like[c] %@";
NSPredicate *predicateToRun6 = [NSPredicate predicateWithFormat:predicateFormat6, self.searchKey];

NSUInteger options = (NSCaseInsensitivePredicateOption|NSDiacriticInsensitivePredicateOption);
NSPredicate *compPred = [NSComparisonPredicate
                         predicateWithLeftExpression:[NSExpression expressionForKeyPath:@"*"]
                         rightExpression:[NSExpression expressionForConstantValue:self.searchKey]
                         modifier:NSDirectPredicateModifier
                         type:NSLikePredicateOperatorType
                         options:options];

predicateToRun = [NSCompoundPredicate orPredicateWithSubpredicates:
                     [NSArray arrayWithObjects:
                      compPred, 
                      predicateToRun, predicateToRun1, predicateToRun2, predicateToRun3, predicateToRun4,   
                      predicateToRun5, predicateToRun6, nil]];

predicateToRun = [NSCompoundPredicate andPredicateWithSubpredicates:
                  [NSArray arrayWithObjects:predicateToRun, [NSPredicate predicateWithFormat:@"(kMDItemContentType != 'public.vcard')"], nil]];

[self.query setPredicate:predicateToRun]; 

[self.query startQuery];

person Uroš Milivojević    schedule 06.10.2011    source источник


Ответы (1)


Я знаю, как это сделать с помощью MDQuery, который, на мой взгляд, проще.

Вы можете использовать в основном те же запросы, что и в mdfind из командной строки.

сделайте строку поиска, например: (НЕ проверено)

((((kMDItemAuthorEmailAddresses == "*john*"cd)) || ((kMDItemAuthors == "*john*"cd))) && (kMDItemContentType == 'com.apple.mail.emlx'))

также в терминале mdls /path/to/library/mail/v2/24324.emlx покажет, где искать электронные письма. Это твой друг

Обратите внимание, как вы можете подключить объективные уведомления c.

NSString* query = some string ;

MDQueryRef mdQuery = MDQueryCreate(nil, (CFStringRef)query, nil, nil);

// if something is goofy, we won't get the query back, and all calls involving a mil MDQuery crash. So return:
if (mdQuery == nil)
    return;

NSNotificationCenter* nf = [NSNotificationCenter defaultCenter];
[nf addObserver:self selector:@selector(progressUpradeQuery:) name:(NSString*)kMDQueryProgressNotification object:(id) mdQuery];
[nf addObserver:self selector:@selector(finishedUpradeQuery:) name:(NSString*)kMDQueryDidFinishNotification object:(id) mdQuery];
[nf addObserver:self selector:@selector(updatedUpradeQuery:) name:(NSString*)kMDQueryDidUpdateNotification object:(id) mdQuery];

// Should I run this query on the network too? Difficult decision, as I think that this will slow stuff way down.
// But i think it will only query leopard servers so perhaps ok
//MDQuerySetSearchScope(mdQuery, (CFArrayRef)[NSArray arrayWithObjects:(NSString*)kMDQueryScopeComputer, (NSString*)kMDQueryScopeNetwork, nil], 0);

// start it
BOOL queryRunning = MDQueryExecute(mdQuery, kMDQueryWantsUpdates); 
if (!queryRunning)
{
    CFRelease(mdQuery);
    mdQuery = nil;
    // leave this log message in...
    NSLog(@"MDQuery failed to start.");
    return;
}

Том

person Tom Andersen    schedule 06.10.2011
comment
У меня были проблемы с MDQueryExecute(mdQuery, kMDQueryWantsUpdates), поэтому я использую MDQueryExecute(mdQuery, kMDQuerySynchronous) и получаю нужные электронные письма - моя обработка в любом случае находится в отдельном потоке. Спасибо! - person Uroš Milivojević; 06.10.2011