UISnapBehavior的这个内存泄漏是否是误报?

时间:2016-05-14 06:47:04

标签: ios objective-c animation memory-leaks

我正在尝试使用UISnapBehaviour为UIButton制作动画。我跟着Apple ReferencesApple Dynamics Catalog,但不是使用点击手势来启动动画,而是在视图启动时自动显示动画启动按钮。我的代码在模拟器中运行,即动画工作,动画结束时按钮也是如此。但即使动画看起来运行正常,Xcode中的Analyzer也会报告内存泄漏。

我尝试在动画仍然有效的几个地方重新定位[self.animator addBehavior:_snapButton];[self.animator removeBehavior:_snapButton];,感觉就像我正确地做了一切。但无论我做什么,我都无法将保留计数设为0.我开始怀疑分析器中可能存在错误。

这是我的代码。我宣布了属性

@interface WaitView ()
    @property (nonatomic, strong) UIDynamicAnimator *animator;
    @property (nonatomic, strong) UISnapBehavior *snapBehavior;
    @end

然后在UIDynamicAnimator

之后初始化[super viewDidLoad]
- (void)viewDidLoad {
    [super viewDidLoad];        //  then tried  [self startButton];
    [self startButton];         // followed by  [super viewDidLoad];

    UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    self.animator = animator;
    [animator release];
}   // Wait view

并在设置动画之前创建了一个UIButton

- (void)startButton {
    CGPoint snapPoint        = CGPointMake(160,284);
    UIButton *wait           = [UIButton buttonWithType:UIButtonTypeCustom];
    wait.frame               = CGRectMake(0, 0, 80, 80);
    [wait setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:@"familyDot%d", 1]] forState:UIControlStateNormal];
    wait.tag                 = 1;
    [wait setTitle:[NSString stringWithFormat:@"%i", 1] forState:UIControlStateNormal];
    [wait setTitleColor:[UIColor blackColor] forState: UIControlStateNormal];
    wait.titleLabel.hidden  = NO;
    [wait addTarget:self action:@selector(tapTest) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:wait];

    [self.animator removeAllBehaviors];
    UISnapBehavior* _snapButton = [[UISnapBehavior alloc] initWithItem:wait snapToPoint:snapPoint];
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    [self.animator addBehavior:_snapButton];
    [_snapButton release];
}

EDIT 根据Kurt的回复,解决方案是使用以下内容替换上面动画代码的最后五行

    UISnapBehavior* _snapButton = [[[UISnapBehavior alloc] initWithItem:wait snapToPoint:target] autorelease];
    self.animator = [[[UIDynamicAnimator alloc] initWithReferenceView:self.view] autorelease];
    [self.animator addBehavior:_snapButton];

并包含按钮的测试。

- (void)tapTest {
    NSLog(@“Start button works!");
}

以下是分析器报告的内存泄漏情况:

    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; 

1。方法返回具有+1保留计数的Objective-C对象

    [self.animator addBehavior:_snapButton];

2。泄漏的对象:此执行路径中未引用已分配的对象,并且保留计数为+1

有人可以告诉我这是否真的是内存泄漏?或者如果我做错了什么?

1 个答案:

答案 0 :(得分:1)

是的,这会导致泄漏。问题全在一条线上:

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

[[UIDynamicAnimator alloc] initWithReferenceView:self.view]返回一个带有+1引用计数的对象。当你完成它时,你有责任发布它。

然后你执行self.animator =该对象。由于它是strong属性,因此它会释放旧对象(如果有)并保留新对象。所以你的对象现在有+2保留计数。

然后从方法返回。假设您遵循通常的内存管理规则并稍后释放strong属性,则只会释放一次该对象。它仍会有+1保留计数,你会泄漏它。

要解决此问题,请完全按照-viewDidLoad中的操作执行操作:

 UIDynamicAnimator *newAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
 self.animator = newAnimator;
 [newAnimator release];

或者:

 self.animator = [[[UIDynamicAnimator alloc] initWithReferenceView:self.view] autorelease];

或转换为ARC!它会为你完成这一切。