3

我有这样的代码:

NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(updateFrame)]];
[invocation setTarget:self];
[invocation setSelector:@selector(updateFrame)];
displayLink_ = [[CADisplayLink displayLinkWithTarget:invocation selector:@selector(invoke)] retain];
[displayLink_ setFrameInterval:1];
[displayLink_ addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

在 iOS 6.0(在 5.1 中,此代码工作正常),当此代码调用时我有两个变体:EXC_BAD_ACCESS 或'调用无法识别的选择器“调用”'。似乎 displayLinkWithTarget:selector: 方法不保留目标。当我添加 [invocation retain] 行时,代码可以正常工作。是iOS 6.0的bug吗?

4

2 回答 2

4

这是有用的相关信息,而不是答案。

而不是使用NSInvokation你可以使用弱代理,就像我在我对这个问题的实际回答中所做的那样。很简单,代码如下:

JAWeakProxy.h:

#import <Foundation/Foundation.h>

@interface JAWeakProxy : NSObject

@property (weak, nonatomic) id  target;

+ (JAWeakProxy*)weakProxyWithTarget:(id)target;

@end

JAWeakProxy.m:

#import "JAWeakProxy.h"

@implementation JAWeakProxy

+ (JAWeakProxy*)weakProxyWithTarget:(id)target
{
    JAWeakProxy* newObj = [self new];
    newObj.target = target;
    return newObj;
}

- (BOOL)respondsToSelector:(SEL)sel
{
    return [_target respondsToSelector:sel] || [super respondsToSelector:sel];
}

- (id)forwardingTargetForSelector:(SEL)sel
{
    return _target;
}

@end

注意:这是 ARC 代码,如果不使用 ARC autorelease,则需要输入。weakProxyWithTarget:

于 2012-12-17T20:00:10.163 回答
2

我有同样的问题。我实际上想要一个弱引用,但由于它被记录为强引用并且在其他版本的 iOS 中表现如此,我使用弱代理对象将选择器转发到我真正想要它去的地方。为了确保保留代理对象,我必须想办法在损坏的 iOS 版本上安全地保留它,而不会为非损坏版本过度保留它。我想出了一个非常优雅的单行解决方案(解释它的四行注释之后的行):

JAWeakProxy*    weakSelf = [JAWeakProxy weakProxyWithTarget:self];
_displayLink = [CADisplayLink displayLinkWithTarget:weakSelf selector:@selector(displayLinkUpdate:)];
// Due to a bug in iOS 6, CADisplayLink doesn't retain its target (which it should and is
// documented to do) so we need to ensure a strong reference to the weak proxy object is
// created somewhere. We do this by adding it as an associated object to the display link
// which means that it gets retained for as long as the display link object is alive.
objc_setAssociatedObject(_displayLink, @"Retain the target, bitch!", weakSelf, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

记得要#import <objc/runtime.h>。使用关联对象非常棒,因为它在显示链接被dealloc编辑时被释放,并且在操作系统的非损坏版本上,它仅仅意味着该对象被显示链接保留两次。

于 2012-12-17T19:49:03.420 回答