【问题标题】:How to write Objective-C Blocks inline?如何内联编写 Objective-C 块?
【发布时间】:2011-04-29 02:22:28
【问题描述】:

我正在尝试使用objective-c 块实现二进制搜索。我正在使用函数indexOfObject:inSortedRange:options:usingComparator:。这是一个例子。

// 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);

【问题讨论】:

    标签: objective-c compare binary-search objective-c-blocks


    【解决方案1】:

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

    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);
    

    【讨论】:

    • 您能否将标题声明添加到您的答案中?
    • 请修正圆括号的位置。它必须是这样的NSComparisonResult (^MakeComparisonBlock)(id,id) = (^(id lhs, id rhs) { ... });。所以不允许我编辑单个字符。
    • @JJD 实际上,这些括号是不必要的。在从内联转换为全局时,我不小心把它们留在了里面,而旧的编译器就让它走了。我会删除它们。
    • 不错!是时候给你答案了。我喜欢!
    【解决方案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);
    

    通过方法调用中的块定义,我得到了与原始实现非常相似的输出。

    【讨论】:

    • 我真的很喜欢你的实现。不过,由于我不能给出 2 个正确答案,我必须决定 @ughoavgfhw,因为我要求使用外部定义的 Objective-c 块。不用担心! - 有趣的是,当我自动完成[self compareNSNumber:id lhs] 时,Xcode 添加了一个冒号和一个错误参数。
    猜你喜欢
    • 2011-08-08
    • 1970-01-01
    • 2017-01-05
    • 2022-12-31
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 2010-10-30
    相关资源
    最近更新 更多