UITapGestureRecognizer导致视图无法解除分配

时间:2016-08-25 07:11:56

标签: ios objective-c

我遇到了一个奇怪的错误:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
    TestView *testView = [[TestView alloc] initWithFrame:self.view.bounds];
    [testView addGestureRecognizer:tap];
    testView.backgroundColor = [UIColor orangeColor];

    [self.view addSubview:testView];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        NSLog(@"testView removeFromSuperview");
        [testView removeFromSuperview];
    });

}


-(void)tap{
    NSLog(@"test");
}

TestView是UIView的子类,在调用-(void)dealloc时打印日志。 如果我什么也不做,等到testView从superview中删除,控制台会记录:

2016-08-25 15:08:30.176 TapTest[12786:238984] testView removeFromSuperview
2016-08-25 15:08:30.176 TapTest[12786:238984] test view dealloc

但是,如果我点击实际触发点按操作的视图,控制台只会记录:

2016-08-25 15:09:43.605 TapTest[12802:240217] test
2016-08-25 15:09:45.306 TapTest[12802:240217] testView removeFromSuperview

我做了很多研究,但仍然不知道发生了什么。

我正在使用Xcode 7.3(7D175)和iOS9。

编辑:我的一位朋友说这与runloop和autorealease池有关,在从superview中删除testView后,我再次点击视图以触发下一个runloop,并取消分配文本视图。

2 个答案:

答案 0 :(得分:0)

我已经想到了什么。

我添加了一些技巧来捕捉弧上的保留计数。 NSLog(@"testView removeFromSuperview -> %d", (int)[testView performSelector:NSSelectorFromString(@"retainCount")]);

无点击:

  

testView removeFromSuperview - > 3

点按:

  

testView removeFromSuperview - > 4

有些东西已经通过点按一次或多次点击事件来轻击手势。我想这是通过相对于主运行循环事件的一些逻辑发生的。

这么好笑的问题。谢谢。我会挖掘更多。

答案 1 :(得分:0)

这可能是由于触控管理系统的实施细节。 正如您在编辑中提到的那样,如果您在移除TestView后再次触摸视图,则会注意到此时它已被取消分配。

如果在dealloc中设置断点,则会在UITouch取消分配时看到它被取消分配。

此时您只能猜测发生了什么,但最可能的事情是iOS保留了UITouch对象发生的最后一次触摸。 a UITouch会保留对触摸发生的视图的引用(请参阅view的{​​{1}}属性)。在这种情况下,这是您的UITouch,这就是为什么它不会立即解除分配。