我创建了一个UITapGesture,其目标不是当前对象。稍后,当点击时,应用程序崩溃。
查看控制器.h:
@interface ViewController : UIViewController
{
IBOutlet UIImageView *iv;
}
@end
查看控制器.c:
#import "ViewController.h"
#import "Target.h"
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
Target *t = [[Target alloc] init];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:t action:@selector(gestureDone:)];
[iv addGestureRecognizer:tgr];
[iv setUserInteractionEnabled:YES];
}
@end
Target.h:
@interface Target : NSObject
- (void)gestureDone:(UIGestureRecognizer *)gr;
@end
Target.c:
@implementation Target
- (void)gestureDone:(UIGestureRecognizer *)gr
{
NSLog(@"Gesture!");
}
@end
(我的XIB文件只包含一张图片......) 点击图像时,它会崩溃。例如,如果我将一个实例变量Target * t添加到我的视图控制器(并在viewDidLoad中删除本地声明),则不会出现任何问题。如果不这样做,我会在Target中覆盖dealloc,在那里放置一个NSLog,并且只要viewDidLoad完成执行就会看到,目标对象就是fred。
我做错了什么,还是有问题? (通常我不会遇到这个问题,因为我使用initWithTarget:self ...)。
答案 0 :(得分:8)
UIGestureRecognizer
未保留其目标。大多数采用目标/动作对的对象都不会保留其目标。这在Cocoa Fundamentals Guide/Communicating with Objects/The Target-Action Mechanism/The Target:
控制对象不会(也不应该)保留其目标。但是,发送操作消息的控件的客户端(通常是应用程序)负责确保其目标可用于接收操作消息。为此,他们可能必须在内存管理的环境中保留其目标。此预防措施同样适用于代表和数据源。
您需要确保以其他方式保留目标,例如在t
的实例变量中存储对ViewController
的引用。
答案 1 :(得分:0)
将目标t
的实例变量添加到ViewController
类并使其变强。这样它就会留在记忆中。