0

テキストを検索するアプリを作成しています(ブロックメソッドを介してテキスト全体を列挙します)。検索コントローラー クラスは、結果を配列にコンパイルし、デリゲート メソッドを介して返します。

デリゲート メソッドを追加する前は結果を取得していたので、検索ロジックが機能していることはわかっています。私が変更したのは、このメソッドをキューで呼び出し、次のようにメイン キューにディスパッチすることです。

searchQueue = dispatch_queue_create("searchQueue", NULL);
dispatch_async(searchQueue, ^{

    dispatch_async(dispatch_get_main_queue(), ^ {
               [controller performSearchWithString:searchText andTexts:[self textsToSearch]];
    });

私がこれを行ったので、実際の配列はこれらのオブジェクトのいずれも取得していません(またはすぐにダンプしていますか?)-常に「null」をログに記録します。理由がわかりません。配列を __block オブジェクトとして宣言しても変更されず、クラスのプロパティとして作成されません。メソッドのコードは次のとおりです。

-(void)performSearchWithString:(NSString *)searchString andTexts:(NSSet *)texts
{

NSMutableArray *pendingResults = nil;
__block int resultsCount = 0;

NSError *error = nil;

for (id book in texts) {
    if ([book isEqual:kBook1]){

        NSURL *url = [[NSBundle mainBundle] URLForResource:@"neiJing" withExtension:@"txt"];



        NSString *text = [NSString stringWithContentsOfURL:url encoding:NSStringEncodingConversionAllowLossy error:&error];
        [text enumerateSubstringsInRange:NSMakeRange(0, [text length])
                                 options:NSStringEnumerationByWords
                              usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                                  //NSRange found = [substring rangeOfString:text];
                                  if ([searchString caseInsensitiveCompare:substring] == NSOrderedSame) {
                                      SearchResult *result = [[SearchResult alloc] init];
                                      result.title = @"neiJing";
                                      result.author = @"Author";
                                      //result.excerpt = substring; // Add logic to configure excerpt range
                                      result.range = NSMakeRange(substringRange.location-500, substringRange.length + 500);
                                      result.excerpt = [NSString stringWithFormat:@"...%@...",[text substringWithRange:result.range]];
                                      [pendingResults addObject:result];
                                      NSLog(@"%@", pendingResults);
                                      resultsCount++;
                                  }
                              }];
    }

if (error == nil) {
    [self.delegate SearchControllerDidReturnResults:[NSArray arrayWithArray:pendingResults]];
}

どんな助けでも大歓迎です。私はまだブロックを理解するのに本当に苦労しており、ストレートな「C」のバックグラウンドはありませんが、変数のスコープがどのように影響を受けるかを把握していると思いました。私はまだ重要な概念を見逃しているようです。

4

1 に答える 1

4

Objective-C の特性の 1 つに遭遇したように思えます。つまり、変数を設定したnilままにして、メッセージを送信できるということです。

プログラムは、エラー メッセージ、警告、または変数が初期化されていない可能性があるその他の兆候なしに、黙って続行します。

したがって、設定pendingResults = nilしてから後で呼び出すと

[pendingResults addObject:result];

その結果、メッセージaddObject:は に送信されnil、結果はまったくなく、コンソール メッセージさえありません。

私の推測では、宣言を次のように変更するとpendingResults

NSMutableArray *pendingResults = [NSMutableArray array];

事が起こり始めます。正しいことではないかもしれません (コードがたくさんあり、多くのことがうまくいかない可能性があります) が、配列に何かが得られます。

この (非) 処理は、nilバグを見つけるのをより困難にする "機能" のように見えるかもしれませんが (実際にそうです)、多くの場合、Objective-C コードは "競合" よりもはるかにクリーンであることも意味します。NullPointerException比較のために、Java を見てみましょう。Java は恐ろしい左右をスローし、多くの人がポインターが null でないかどうかのテストをコードに散らかしています。

したがって、Objective-C のこの独特な側面のこつをつかむと、デバッガーで最初にチェックすることの 1 つになります (そして、デバッガーを使用しますね?)。

于 2013-04-01T18:15:02.220 に答える