我遇到了一个奇怪的错误:
- (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,并取消分配文本视图。答案 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
,这就是为什么它不会立即解除分配。