Objective-C로 작성된 빠른 및 최소 임베드 된 전체 텍스트 인덱싱 라이브러리.
지금 까지이 라이브러리를 프로젝트에 통합하는 가장 쉬운 방법은 코코아포드를 사용하는 것입니다.
아직 그렇지 않은 경우 코코 포드를 설치하십시오
포드 파일에 라인을 추가하십시오
pod 'MHTextSearch'
pod install 실행하십시오
프로젝트에 libc++.dylib 프레임 워크를 추가하십시오.
MHTextIndex *index = [MHTextIndex textIndexInLibraryWithName: @" my.awesome.index " ]; MHTextIndex 인스턴스에 객체 (모든 개체)를 색인화 할 수 있습니다.
[ index indexObject: anyObjectYouWant];
[ index updateIndexForObject: anotherPreviousIndexedObject];
[ index removeIndexForObject: anotherPreviousIndexedObject]; 그러나 이것이 작동하려면 NSData * 로서 어떤 식별자를 사용 하여이 개체를 고유하게 참조 할 수 있는지 알려야합니다.
[ index setIdentifier: ^ NSData *(MyCustomObject *object){
return object. indexID ; // a NSData instance
}];또한 인덱스 텍스트 조각과 같은 개체에 대한 세부 정보도 제공해야합니다.
[ index setIndexer: ^MHIndexedObject *(MyCustomObject *object, NSData *identifier){
MHIndexedObject *indx = [MHIndexedObject new ];
indx. strings = @[ object.title, object.description ]; // Indexed strings
indx. weight = object. awesomenessLevel ; // Weight given to this object, when sorting results
indx. context = @{ @" title " : object. title }; // A NSDictionary that will be given alongside search results
return indx;
}];마지막으로, 검색 결과를 얻을 때 원래 객체를 쉽게 참조 할 수 있으려면, 당신을 위해 그것을하는 방법을 알려줄 수 있습니다.
[ index setObjectGetter: ^MyCustomObject *( NSData *identifier){
return [MyCustomObject customObjectFromIdentifier: identifier];
}];그리고 그게 다야! 이것이 바로 전체 텍스트 색인을 얻는 데 필요한 전부입니다. Mhtextearch는 예상대로 로케일과 관련하여 텍스트를 단어로 나누고 디아크리닉 및 대문자를 고려합니다 (Well, Foundation은 대부분의 작업을 수행합니다).
그런 다음 검색을 시작할 수 있습니다.
[ index enumerateObjectsForKeyword: @" duck " options: 0 withBlock: ^(MHSearchResultItem *item,
NSUInteger rank,
NSUInteger count,
BOOL *stop){
item. weight ; // As provided by you earlier
item. rank ; // The effective rank in the search result
item. object ; // The first time it is used, it will use the block
// you provided earlier to get the object
item. context ; // The dictionary you provided in the "indexer" block
item. identifier ; // The object identifier you provided in the "identifier" block
NSIndexPath *token = item. resultTokens [ 0 ];
/* This is an NSArray of NSIndexPath instances, each containing 3 indices:
* - mh_string : the string in which the token occured
* (here, 0 for the object's title)
* - mh_word : the position in the string where the word containing
* the token occured
* - mh_token : the position in the word where the token occured
*/
NSRange tokenRange = [item rangeOfToken: token];
/* This gives the exact range of the matched token in the string where it was found.
*
* So, according to the example setup I've been giving from the start,
* if token.mh_string == 0, that means the token was found in the object's "title",
* and [item.object.title substringWithRange:tokenRange] would yield "duck" (minus
* capitalization and diacritics).
*/
}]; MHSearchResultItem 인스턴스의 전체 배열을 한 번에 가져올 수도 있습니다.
NSArray *resultSet = [ index searchResultForKeyword: @" duck "
options: NSEnumerationReverse];동작을 지정하기위한 블록을 제공하는 경우 다음 방법을 무시할 수도 있습니다.
-[MHTextIndex getIdentifierForObject:] 기본적으로 identifier 블록을 사용합니다-[MHTextIndex getIndexInfoForObject:andIdentifier:] 기본적으로 indexer 블록을 사용합니다-[MHTextIndex compareResultItem:withItem:reversed:] 검색 결과 세트를 주문하는 데 사용됩니다. NSManagedObject 라이프 사이클 방법을 사용하여 텍스트 인덱스의 변경 사항을 트리거 할 수 있습니다. 다음 예는 http://www.adevelopingstory.com/blog/2013/04/adding-full-text-search-to-core-data.html에서 가져 왔으며이 프로젝트에서 사용하도록 조정되었습니다.
- ( void )prepareForDeletion
{
[ super prepareForDeletion ];
if (self. indexID . length ) {
[textindex deleteIndexForObject: self .indexID];
}
}
+ ( NSData *)createIndexID {
NSUUID *uuid = [ NSUUID UUID ];
uuid_t uuidBytes;
[uuid getUUIDBytes: uuidBytes];
return [ NSData dataWithBytes: uuidBytes length: 16 ];
}
- ( void )willSave
{
[ super willSave ];
if (self. indexID . length ) {
[textindex updateIndexForObject: self .indexID];
} else {
self. indexID = [[ self class ] createIndexID ];
[textindex indexObject: self .indexID];
}
} MHTextIndex 후드 아래에서 NSOperationQueue 사용하여 인덱싱 작업을 조정합니다. indexingQueue 라는 속성으로 노출됩니다. 따라서 maxConcurrentOperationCount 속성을 설정하여 인덱싱이 얼마나 동시에 있는지 제어 할 수 있습니다. I/O를 수행하는 기본 데이터베이스 라이브러리는 스레드 안전이므로 동시성은 문제가되지 않습니다. 이것은 또한 인덱싱 작업이 사용을 완료 할 때까지 명시 적으로 기다릴 수 있음을 의미합니다.
[ index .indexingQueue waitUntilAllOperationsAreFinished ]; 세 가지 인덱싱 방법 -[MHTextIndex indexObject:] , -[MHTextIndex updateIndexForObject:] , -[MHTextIndex removeIndexForObject:] 모든 반환 NSOperation 인스턴스, 필요한 경우, completionBlock 속성 또는 -[NSOperation waitUntilFinished] 메소드를 이용할 수 있습니다.
검색도 동시에 있지만 dispatch_queue_t (아직 노출되지 않거나 조정할 수 없음)를 사용합니다.
mhtextseach가 당신의 요구에 더 잘 맞도록하기 위해 놀 수있는 몇 개의 손잡이가 있습니다.
MHTextIndex 인스턴스에는 기본적으로 사실이며 매우 일반적인 영어 단어를 색인화하는 것을 피하는 skipStopWords 부울 속성이 있습니다. ( Todo : 다른 언어와 함께 작동하십시오)
또한 기본적으로 2 와 같은 minimalTokenLength 길이가 있습니다. 이것은 토큰을 색인화하기 위해 토큰이 필요한 글자 수에 대해 최소를 설정합니다. 또한 인덱스 및 검색 시간뿐만 아니라 인덱스의 크기를 크게 최소화합니다. 단일 레터 단어와 모든 단어의 마지막 문자를 2 로 설정할 때 인덱싱하는 인덱스를 건너칩니다.
긴 양식 텍스트 (예 : 간단한 이름이 아닌 문서)를 색인화 할 때 MHTextIndex 에서 discardDuplicateTokens 부울 속성을 켤 수 있습니다. 이로 인해 인덱스는 주어진 텍스트에 대한 모든 인덱스 토큰의 첫 번째 발생 만 고려합니다. 토큰이 텍스트로 나타나는 지 아는 것이 좋으면 모든 발생이 나타나는 곳이 아닌 인덱싱 시간에 3 ~ 5의 속도 범프를 얻을 수 있습니다.
다음 그래프는 500kb에서 약 10MB 범위의 텍스트 크기의 함수로 인덱싱 및 검색 시간 (초)을 보여줍니다. 벤치 마크는 iPhone 5에서 실행되었습니다.
테스트를 실행하려면 테스트 스위트가 새로운 XCTest를 사용하므로 Xcode 5가 필요합니다.
이 저장소를 복제하고 일단 안으로
$ cd MHTextSearch iOS Tests
$ pod install
$ cd .. && open * .xcworkspace현재 모든 테스트는 iOS 테스트 스위트와 함께 작동하도록 설정되었습니다.
MIT 라이센스에 따라 배포됩니다