【问题标题】:Automatic Reference Counting: Error with fast enumeration自动引用计数:快速枚举错误
【发布时间】:2011-10-19 00:33:49
【问题描述】:

在更新下面的代码以使用 iOS 5 的自动引用计数时,在尝试执行快速枚举时为“state->itemPtr”分配缓冲区时发生错误,以便可以使用“迭代实现类” foreach”循环。我得到的错误是“将'__autoreleasing id *'分配给'__unsafe_unretained id*'会更改指针的保留/释放属性”。请参阅带有注释的代码行。

/*
 * @see http://cocoawithlove.com/2008/05/implementing-countbyenumeratingwithstat.html
 * @see http://www.mikeash.com/pyblog/friday-qa-2010-04-16-implementing-fast-enumeration.html
 */
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state objects: (id *)buffer count: (NSUInteger)bufferSize {
    NSUInteger arrayIndex = (NSUInteger)state->state;
    NSUInteger arraySize = [_tuples count];
    NSUInteger bufferIndex = 0;

    while ((arrayIndex < arraySize) && (bufferIndex < bufferSize)) {
        buffer[bufferIndex] = [_tuples objectAtIndex: arrayIndex];
        arrayIndex++;
        bufferIndex++;
    }

    state->state = (unsigned long)arrayIndex;
    state->itemsPtr = buffer; // Assigning '__autoreleasing id *' to '__unsafe_unretained id*' changes retain/release properties of pointer
    state->mutationsPtr = (unsigned long *)self;

    return bufferIndex;
}

本例中的 _tuples 变量是 NSMutableArray 类型的实例变量。

如何解决此错误?

【问题讨论】:

    标签: objective-c ios ios5 automatic-ref-counting


    【解决方案1】:

    你需要把缓冲区改成__unsafe_unretained:

    - (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state
                                       objects: (id __unsafe_unretained *)buffer
                                         count: (NSUInteger)bufferSize
    

    source

    编辑:消除mutationPtr 中的错误的简单方法:

    state->mutationsPtr = &state->extra[0];
    

    【讨论】:

    • 但是在我执行“转换为 Objective-C ARC”之后,Xcode 更改了“state->mutationsPtr = (unsigned long *)self;”到“state->mutationsPtr = (__bridge unsigned long *)self;”。这现在导致另一个错误说“不兼容的类型将 *const __strong 转换为 unsigned long 与 __bridge 转换”有什么想法吗?
    • state-&gt;mutationsPtr 不应用于存储self,它应该指向未使用的额外字段(简单方法)或指向类中的某种内部值集合更改(艰难的方式),我将编辑答案以包含简单的方式。
    • 这真的有效吗?以不同方式定义objects 参数?这会在我的系统上产生编译器错误——它与声明不匹配。
    • NSEnumerator.h 中的定义是- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len;
    【解决方案2】:

    紫敏姬,

    我遇到了同样的问题,这就是我遇到这个问题的原因。

    我通过 保持objects 参数的定义原样解决了这个问题(例如,保持它为 id *),而是使用 void 指针进行双重转换。

    所以,虽然这对我产生了错误:

    state->itemsPtr = (__unsafe_unretained id *)buffer  // Error
    

    效果很好:

    state->itemsPtr = (__unsafe_unretained id *)(void *)buffer  // No error
    

    免责声明:我不是 ARC 专家,我不能向您保证这不会导致引用计数问题。但是,它似乎在我的测试中正常工作,并且它肯定在没有警告的情况下编译。

    顺便说一句,我看到了这篇由两部分组成的博客文章,其中深入介绍了快速枚举:

    还有__unsafe_unretained上的这篇博文:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      • 2011-12-28
      • 2020-05-19
      • 2013-04-26
      • 1970-01-01
      相关资源
      最近更新 更多