目标c - 更新块中的参数

时间:2016-05-17 22:48:07

标签: objective-c segmentation-fault objective-c-blocks

我正在修改树遍历(我已经用更直接的方式解决了)但我在下面的Objective C逻辑中遇到了一个问题:

- (NSString *)someWrapperFunction
{
    NSString *result = @"";

    NSString *(^appendBlock)(int, NSString **) = ^NSString *(int a, NSString **adder){
        if (a == 0)
        {
            // base case
            return @"";
        }

        NSLog(@"%d", a);

        *adder = [*adder stringByAppendingFormat:@"-%d-", a];

        NSLog(@"adder: %@", *adder);
        return [*adder stringByAppendingString:appendBlock(a-1, adder)];
    };

    appendBlock(5, &result);

    return result; 
}

基本上,我想创建一个代码块,将数字连接到给定的字符串(adder)。结果应为:"-5--4--3--2--1-"

我使用上面的代码得到了分段错误,但是我为树遍历编写了一些其他代码,加法器字符串基本上没有得到更新。我在这里做错了什么指针? (内部块(内部递归)正在更新的变量是否可能被禁止,因为它已经被外部块占用或者只是NSString是非可变数据类型?)< / p>

无论如何,我想保持功能的设计相同;我将如何解决这个问题(使用c / objective)?

1 个答案:

答案 0 :(得分:1)

经过一番搜索和实验后,我找到了解决这个问题的方法。

  1. 没有理由在块中为adder参数使用双指针。只需使用常规指针并相应地更新代码。
  2. 错误来自于块内部,appendBlockNULL并且您最终取消引用试图调用它的NULL指针。
  3. 这是一个有效的更新版本:

    - (NSString *)someWrapperFunction
    {
        NSString *result = @"";
    
        NSString *(^appendBlock)(int, NSString *);
        __block __weak NSString *(^weakBlock)(int, NSString *);
        weakBlock = appendBlock = ^NSString *(int a, NSString *adder){
            NSString *(^innerBlock)(int, NSString *) = weakBlock;
            if (a == 0)
            {
                // base case
                return @"";
            }
    
            NSLog(@"%d", a);
    
            adder = [adder stringByAppendingFormat:@"-%d-", a];
    
            NSLog(@"adder: %@", adder);
    
            // Split this update to make it easier to debug.
            NSString *update = innerBlock(a-1, adder);
            return [adder stringByAppendingString:update];
        };
    
        appendBlock(5, result);
    
        return result; 
    }
    

    输出:"-5--4--3--2--1-"

    此更新将针对第1点进行重写(这与您的原始问题无关。

    要解决第2点,此更新会创建原始appendBlock变量以及对同一块的新__block __weak weakBlock引用。然后在块内部,创建一个新的(强)块指针来引用弱块指针。如果不使用弱指针,代码会起作用但会引发警告。