2010-10-22 45 views
7

我正在尝试使用objective-c块实现二分搜索。我正在使用功能indexOfObject:inSortedRange:options:usingComparator:。这是一个例子。如何在内联中编写Objective-C块?

// A pile of data. 
NSUInteger amount = 900000; 
// A number to search for. 
NSNumber* number = [NSNumber numberWithInt:724242]; 

// Create some array. 
NSMutableArray* array = [NSMutableArray arrayWithCapacity:amount]; 
for (NSUInteger i = 0; i < amount; ++i) {; 
    [array addObject:[NSNumber numberWithUnsignedInteger:i]]; 
} 
NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; 

// Run binary search. 
int index1 = [array indexOfObject:number 
        inSortedRange:NSMakeRange(0, [array count]) 
          options:NSBinarySearchingFirstEqual 
        usingComparator:^(id lhs, id rhs) { 
         if ([lhs intValue] < [rhs intValue]) { 
          return (NSComparisonResult)NSOrderedAscending; 
         } else if([lhs intValue] > [rhs intValue]) { 
          return (NSComparisonResult)NSOrderedDescending; 
         } 
         return (NSComparisonResult)NSOrderedSame; 
        }]; 
NSTimeInterval stop1 = [NSDate timeIntervalSinceReferenceDate]; 
NSLog(@"Binary: Found index position: %d in %f seconds.", index1, stop1 - start); 

// Run normal search. 
int index2 = [array indexOfObject:number]; 
NSTimeInterval stop2 = [NSDate timeIntervalSinceReferenceDate]; 
NSLog(@"Normal: Found index position: %d in %f seconds.", index2, stop2 - start); 

我想知道如何使用上述函数的外部定义的objective-c块。这里有两个比较函数。

NSComparisonResult compareNSNumber(id lhs, id rhs) { 
    return [lhs intValue] < [rhs intValue] ? NSOrderedAscending : [lhs intValue] > [rhs intValue] ? NSOrderedDescending : NSOrderedSame; 
} 
NSComparisonResult compareInt(int lhs, int rhs) { 
    return lhs < rhs ? NSOrderedAscending : lhs > rhs ? NSOrderedDescending : NSOrderedSame; 
} 

这些都是参考以下声明书写的,可以在NSObjCRuntime.h中找到。

enum _NSComparisonResult {NSOrderedAscending = -1, NSOrderedSame, NSOrderedDescending}; 
typedef NSInteger NSComparisonResult; 
typedef NSComparisonResult (^NSComparator)(id obj1, id obj2); 

回答

21

您可以将块定义为全局变量以获得类似于函数的效果。

NSComparisonResult (^globalBlock)(id,id) = ^(id lhs, id rhs) { 
    if([lhs intValue] < [rhs intValue]) { 
     return (NSComparisonResult)NSOrderedAscending; 
    } else if([lhs intValue] > [rhs intValue]) { 
     return (NSComparisonResult)NSOrderedDescending; 
    } 
    return (NSComparisonResult)NSOrderedSame; 
}; 

然后,在方法做比较:

int index1 = [array indexOfObject:number 
        inSortedRange:NSMakeRange(0, [array count]) 
          options:NSBinarySearchingFirstEqual 
        usingComparator:globalBlock]; 

为了把块的头,外用:

NSComparisonResult (^globalBlock)(id,id); 
+0

您可以请将标题声明添加到您的答案? – JJD 2011-01-21 09:21:18

+0

请更正圆括号的位置。它必须像这样:NSComparisonResult(^ MakeComparisonBlock)(id,id)=(^(id lhs,id rhs){...});'。 SO不允许我编辑单个字符。 – JJD 2011-10-10 12:41:59

+0

@JJD其实,这些括号是不必要的。当从内联转换到全局时,我意外地将它们留在了原来的位置,而较老的编译器也放弃了它。我会删除它们。 – ughoavgfhw 2011-10-10 14:27:14

2

我知道这是老了,但我只是碰到它跑了,我一直想在我的块foo的工作,所以这里去...

我创建了返回您NSComparator的方法作为一个块。它看起来像这样:

-(NSComparisonResult (^) (id lhs, id rhs))compareNSNumber{ 

return [[^(id lhs, id rhs) 
     { 
      return [lhs intValue] < [rhs intValue] ? (NSComparisonResult)NSOrderedAscending : [lhs intValue] > [rhs intValue] ? (NSComparisonResult)NSOrderedDescending : (NSComparisonResult)NSOrderedSame; 

     } copy ] autorelease]; 
} 

当时我能够通过改变二进制搜索执行,以运行示例代码:

// Run binary search. 
int index1 = [array indexOfObject:number 
        inSortedRange:NSMakeRange(0, [array count]) 
          options:NSBinarySearchingFirstEqual 
        usingComparator:[self compareNSNumber]]; 
NSTimeInterval stop1 = [NSDate timeIntervalSinceReferenceDate]; 
NSLog(@"Binary: Found index position: %d in %f seconds.", index1, stop1 - start); 

我非常相似的输出到了原来实行与内块定义方法调用。

+0

我真的很喜欢您的实现。虽然,因为我不能给出2个正确答案,所以我必须决定@ ughoavgfhw,因为我要求一个外部定义的Objective-C块。别担心! - 有趣的是,当我自动完成'[self compareNSNumber:id lhs]'时,Xcode添加了一个冒号和一个错误参数。 – JJD 2011-10-10 12:50:18