如何在协议实现的参数中强制执行__weak引用

时间:2022-10-02 16:10:16

I have a protocol for which I want the implementations to use __weak references for method arguments. I define my protocol as:

我有一个协议,我希望实现使用__weak引用方法参数。我将我的协议定义为:

@protocol TestProtocol
-(void) op:(__weak NSObject*)x;
@end

Then I create an implementation:

然后我创建一个实现:

-(void) op:(NSObject*)x
{
}

And x becomes an strong reference. If I move the __weak declaration to the protocol implementation, 'x' is a weak reference.

并且x成为强有力的参考。如果我将__weak声明移动到协议实现,'x'是弱引用。

As the caller of the protocol already keeps a strong reference, I want to ensure that the implementations don't create another strong reference.

由于协议的调用者已经保留了强大的引用,我想确保实现不会创建另一个强引用。

1 个解决方案

#1


3  

I'm a tad surprised the compiler doesn't complain about a declaration mismatch. And, sure enough, it doesn't. I filed radar #13730581 to see what the compiler folks say.

我有点惊讶编译器不会抱怨声明不匹配。而且,果然,它没有。我提交了雷达#13730581,看看编译人员说的是什么。

As @hypercrypt cites, ARC isn't going to retain or release the arguments to a method in the general case. One of the few cases where the performance vs. correctness sacrifice was large enough to warrant such a tradeoff. (Note that you'll see a storeStrong in the non-optimized case but no such thing in the -Os case Release build case).

正如@hypercrypt引用的那样,ARC不会在一般情况下保留或释放方法的参数。性能与正确性牺牲的少数情况之一足以保证这种权衡。 (请注意,您将在非优化案例中看到storeStrong,但在-Os案例版本构建案例中没有这样的事情)。

Which means you are really defending against a strong reference being created against the object by implication of the code in the method body (and, as per comments, that said strong reference isn't torn down when an @throw goes "over" the frame).

这意味着你实际上是通过方法体中的代码暗示来防御针对该对象创建的强引用(并且根据评论,当@throw超过“框架”时,所述强引用不会被拆除)。

There isn't much you can do about that -- if you pass x off to, say, NSMutableArray's addObject: method, it'll create a strong reference.

你可以做的事情并不多 - 如果你把x传递给NSMutableArray的addObject:方法,它会创建一个强引用。

Thus, in the general case, there isn't really a means of preventing a strong reference to an object from being created as a side effect of variable usage.

因此,在一般情况下,实际上没有一种方法可以防止对对象的强引用被创建为可变使用的副作用。

Specific to NSException cleanup, it isn't worth worrying about. Exceptions should be fatal and the state of the app after an exception is thrown is undefined (unless you can ensure that no system code was in any way involved with the exception, which isn't really viable).

具体到NSException清理,不值得担心。异常应该是致命的,并且在抛出异常之后应用程序的状态是未定义的(除非您可以确保没有系统代码以任何方式涉及异常,这实际上是不可行的)。

// code tossed in main.m to play w/compiler behavior

@protocol TestProtocol
-(void) op:(__weak NSObject*)x;
@end

@interface DogBowl:NSObject <TestProtocol>
@end
@implementation DogBowl
-(void) op:(NSObject*)x
{
}
@end

#1


3  

I'm a tad surprised the compiler doesn't complain about a declaration mismatch. And, sure enough, it doesn't. I filed radar #13730581 to see what the compiler folks say.

我有点惊讶编译器不会抱怨声明不匹配。而且,果然,它没有。我提交了雷达#13730581,看看编译人员说的是什么。

As @hypercrypt cites, ARC isn't going to retain or release the arguments to a method in the general case. One of the few cases where the performance vs. correctness sacrifice was large enough to warrant such a tradeoff. (Note that you'll see a storeStrong in the non-optimized case but no such thing in the -Os case Release build case).

正如@hypercrypt引用的那样,ARC不会在一般情况下保留或释放方法的参数。性能与正确性牺牲的少数情况之一足以保证这种权衡。 (请注意,您将在非优化案例中看到storeStrong,但在-Os案例版本构建案例中没有这样的事情)。

Which means you are really defending against a strong reference being created against the object by implication of the code in the method body (and, as per comments, that said strong reference isn't torn down when an @throw goes "over" the frame).

这意味着你实际上是通过方法体中的代码暗示来防御针对该对象创建的强引用(并且根据评论,当@throw超过“框架”时,所述强引用不会被拆除)。

There isn't much you can do about that -- if you pass x off to, say, NSMutableArray's addObject: method, it'll create a strong reference.

你可以做的事情并不多 - 如果你把x传递给NSMutableArray的addObject:方法,它会创建一个强引用。

Thus, in the general case, there isn't really a means of preventing a strong reference to an object from being created as a side effect of variable usage.

因此,在一般情况下,实际上没有一种方法可以防止对对象的强引用被创建为可变使用的副作用。

Specific to NSException cleanup, it isn't worth worrying about. Exceptions should be fatal and the state of the app after an exception is thrown is undefined (unless you can ensure that no system code was in any way involved with the exception, which isn't really viable).

具体到NSException清理,不值得担心。异常应该是致命的,并且在抛出异常之后应用程序的状态是未定义的(除非您可以确保没有系统代码以任何方式涉及异常,这实际上是不可行的)。

// code tossed in main.m to play w/compiler behavior

@protocol TestProtocol
-(void) op:(__weak NSObject*)x;
@end

@interface DogBowl:NSObject <TestProtocol>
@end
@implementation DogBowl
-(void) op:(NSObject*)x
{
}
@end