1

在下面的代码中,当我在 GCC_OPTIMIZATION_LEVEL 设置为 None 的情况下运行它时,执行工作如我所料,并将以下内容打印到控制台:

My Obj - SomeObj

但是,当我在 Xcode 目标配置中将 GCC_OPTIMIZATION_LEVEL 设置为 Fastest, Smallest 时(通常用于发布版本),我最终会在控制台上打印以下内容:

My obj - (null)

当我将对象存储到 [Foo doSomething] 中的 __weak id myObj 变量中时,该对象似乎正在被释放。如果我从 myObj 变量中删除 __weak 标志,则当 GCC_OPTIMIZATION_LEVEL 设置为 Fastest, Smallest 时,代码将按预期运行。

我基于我在另一个项目中的类似模式构建了这个示例,并添加了 __weak 标志,因为我遇到了保留周期。保留周期警告消失了,但是当我为 Release 构建时,我发现 myObj 在到达我在此示例中记录它的位置时将为零。

设置 __weak 标志违反了哪些规则?

#import "FFAppDelegate.h"


///////////////////////////////////////////////////////
@interface SomeObject : NSObject

@end

@implementation SomeObject

- (NSString *)description; {
    return @"SomeObject";
}

@end


///////////////////////////////////////////////////////
@interface Factory : NSObject
@end

@implementation Factory

- (id)generateObj {
    id myObj = nil;
    if (!myObj) {
        SomeObject *anObj = [[SomeObject alloc] init];
        myObj = anObj;
    }
    return myObj;
}


@end


///////////////////////////////////////////////////////
@interface Bar : NSObject

- (id)barObj;

@end

@implementation Bar
{
    Factory *factory;
}

- (id)init {
    self = [super init];
    if (self) {
        factory = [[Factory alloc] init];
    }
    return self;
}
- (id)barObj {
    id anObj = [factory generateObj];
    return anObj;
}

@end


///////////////////////////////////////////////////////
@interface Foo : NSObject

@property (strong) Bar *aBar;

- (void)doSomething;

@end

@implementation Foo

- (id)init {
    self = [super init];
    if (self) {
        _aBar = [[Bar alloc] init];
    }
    return self;
}

- (void)doSomething {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        __weak id myObj = [self.aBar barObj];
        NSLog(@"My Obj - %@", myObj);
    });
}

@end


///////////////////////////////////////////////////////
@implementation FFAppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    Foo *f = [[Foo alloc] init];
    [f doSomething];
}

@end
4

2 回答 2

3

设置 __weak 标志违反了哪些规则?

在您的示例中,没有对从[self.aBar barObj]. 因此,您不能假设实例在您读取myObj变量时仍处于活动状态。

在未优化的构建中,返回的实例已添加到自动释放池中,因此在您 print 时仍然存在myObj。您可以通过在 中设置断点来验证这一点-[SomeObject dealloc]

在优化的构建中,ARC 避免了自动释放池,因此返回的实例被立即释放。

有关详细信息,请参阅Clang ARC 文档中的第 3.2.3 节。具体来说:

当从这样的函数或方法返回时,ARC 在返回语句的求值点保留值,然后离开所有局部范围,然后平衡保留,同时确保值跨越调用边界。在最坏的情况下,这可能涉及自动释放,但调用者不能假设该值实际上在自动释放池中

__weak用于避免保留循环时,您必须确保在其他地方存在强引用以保持对象处于活动状态。

于 2013-05-25T05:56:59.657 回答
-1

也许您应该使用 Apple 的默认编译器 LLVM 而不是 GCC。

编辑:您的“工厂”方法也看起来不对。例如,对象在那个 if 中总是 nil。参观:http: //developer.apple.com/library/ios/#documentation/general/conceptual/CocoaEncyclopedia/ClassFactoryMethods/ClassFactoryMethods.html

于 2013-05-25T07:57:06.957 回答