关于C#:“__ block”变量在走出块时导致nil值

“__block” variable results in nil value when go out of block

我想使用__block变量来获取块中的值。 但是当阻塞时,__block变量似乎是零。 为什么会这样?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    NSString *fileName = [Tools MD5Encode:url];
    __block NSString *filePath = nil;
    [fileList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSString *aFileName = obj;
        if ([aFileName isEqualToString:fileName]) {
            NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName];
            filePath = path;
            NSLog(@"filePath1 %@", filePath);
            *stop = YES;
        }
    }];
    //NSLog(@"filePath2 %@", filePath);
    //filePath seems to be nil
    return filePath;

当我将代码更改为[路径复制]时,它可以工作。 但我不知道这是不是一个好主意。 任何决定?

1
2
3
4
5
6
7
8
9
10
11
12
13
    NSString *fileName = [Tools MD5Encode:url];
    __block NSString *filePath = nil;
    [fileList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSString *aFileName = obj;
        if ([aFileName isEqualToString:fileName]) {
            NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName];
            filePath = [path copy];
            NSLog(@"filePath1 %@", filePath);
            *stop = YES;
        }
    }];
    //NSLog(@"filePath2 %@", filePath);
    return [filePath autorelease];


http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

特别:

Without ARC, __block also has the side effect of not retaining its contents when it's captured by a block. Blocks will automatically retain and release any object pointers they capture, but __block pointers are special-cased and act as a weak pointer. It's become a common pattern to rely on this behavior by using __block to avoid retain cycles.

Under ARC, __block now retains its contents just like other captured object pointers. Code that uses __block to avoid retain cycles won't work anymore. Instead, use __weak as described above.

所以你需要复制。


在这里使用块甚至是一个问题吗?

在我看来这段代码:

1
2
3
4
NSString *filePath = nil;
NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName];
filePath = path;
return [filePath autorelease];

过度释放filePath(因为你没有-stringByAppendingPathComponent:的结果,你不应该(自动)释放它)


这里可以使用路径上的复制或保留。 您遇到问题的原因是NSString对象是方便对象的成员以及NSArray之类的其他对象,您实际上不必释放这些对象,并且在ARC出现之前已经由系统自动释放。 就个人而言,我不喜欢他们这样做,因为它只是造成了这样的混乱。 因为块完成执行系统自动释放您分配的字符串对象导致泄漏。