Obj-C __block变量保留行为

| 尝试从修改了变量的块外部访问
__block
(块可变)变量时遇到一个奇怪的问题。这是一个非常有趣的示例,我只是为了更好地理解块而已,但是目前,我有一个使用此方法的控制器,该控制器创建一个字符串,其内容为
NSDictionary
的内容,该内容使用
NSDictionary
\的
enumerateKeysAndObjectsUsingBlock:
- (NSString*) contentsOfDictionary:(NSDictionary*)dictionary
{
    __block NSString *content = @\"\";

    [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
        NSString* contentToAppend = [NSString stringWithFormat:@\"Object:%@ for key:%@\\n\", obj, key];
        content = [content stringByAppendingString:contentToAppend];
        NSLog(@\"Content in block:\\n%@\", content);
    }];

    NSLog(@\"Content out of block:\\n%@\", content);

    return content;
}
当我使用包含内容的字典运行此方法时:
Value    Key
\"Queen\"  \"card\"
\"Hearts\" \"suit\"
\"10\"     \"value\"
the6ѭ变量在块中正确修改,每次迭代我都得到以下输出: ...内容在区块中:
Object:Queen for key:card
...内容在区块中:
Object:Queen for key:card
Object:Hearts for key:suit
...内容在区块中:
Object:Queen for key:card
Object:Hearts for key:suit
Object:10 for key:value
但是,一旦代码退出该块,访问
content
字符串将抛出
EXC_BAD_ACCESS
,并且在一次运行时,它似乎已经打印了一些垃圾内存(无法重现)... 是什么导致此变量提前释放?我的印象是,给它一个“ 0”定义意味着它在块中使用时将保留,并在块退出时被释放-但是由于是字符串文字,因此保留并自动释放了变量,因此我期望直到此方法最早退出后,才可以对其进行分配。     
已邀请:
        这是你的问题:
content = [content stringByAppendingString:contentToAppend];
-stringByAppendingString:
返回一个新的自动释放的对象。该对象的地址存储在“ 6”中。每次经过这个(隐式)循环(即,对所提供的块的每次调用)都在创建一个全新的对象,然后将该新对象的地址分配给“ 6”。这些对象均未超过其包含的自动释放池。 您应该做的是使用
NSMutableString
并将
contentToAppend
直接附加到可变字符串上。例如:
- (NSString*) contentsOfDictionary:(NSDictionary*)dictionary
{
    NSMutableString *content = [NSMutableString string];
    [dictionary enumerateKeysAndObjectsUsingBlock:
    ^(id key, id obj, BOOL *stop){
        NSString* contentToAppend = [NSString stringWithFormat:
            @\"Object:%@ for key:%@\\n\", obj, key];
        [content appendString:contentToAppend];

        NSLog(@\"Content in block:\\n%@\", content);
    }];

    NSLog(@\"Content out of block:\\n%@\", content);
    return content;
}
注意,不再需要
__block
,因为您不会在块内的任何地方分配assign6ѭ。     
        在内部,ѭ22使用自动释放池。
__block
范围内的对象不会在块的生存期结束后保留​​,因此您最终会在块的范围内创建一个对象,然后在耗尽字典的自动释放池时将其释放,所有尝试打印
content
的值之前发生。     

要回复问题请先登录注册