2016-05-14 6 views
0

UISnapBehaviourを使用してUIButtonをアニメーション化しようとしています。私はApple ReferencesApple Dynamics Catalogを追跡しましたが、タップジェスチャーを使ってアニメーションを開始するのではなく、ビューが起動するとアニメーション開始ボタンが自動的に表示されます。私のコードはシミュレータで実行されます。つまり、アニメーションは動作し、アニメーションが終了するとボタンも動きます。しかし、アニメーションは正常に動作するように見えますが、XcodeのAnalyzerはメモリリークを報告します。このメモリリークはUISnapBehaviorで誤ったアラームですか?

[self.animator addBehavior:_snapButton];[self.animator removeBehavior:_snapButton];をアニメーションがまだ動作しているいくつかの場所で再配置しようとしましたが、すべてが正しく動作しているように感じました。しかし、私が何をしても、保持カウントを0にすることはできません。アナライザーにバグが存在する可能性があると思われ始めています。

ここに私のコードです。私は性質が

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

が、その後[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 

UIDynamicAnimatorを初期化宣言し、それ

- (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をアニメーション化する前にUIButtonを作成しましたクルトの応答に基づいて、ソリューションには、次の

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


とボタンのテストを含めて上に私のアニメーションコードの最後の5行を交換することです。ここ

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

アナライザによって報告されたメモリリークの内訳である:

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

1.方法+1カウントを保持

[self.animator addBehavior:_snapButton]; 
とObjective-Cのオブジェクトを返します

2.オブジェクトがリークしました:割り当てられたオブジェクトはこの実行パスで後で参照されず、+1の保持カウントを持ちます

これは本当にメモリリークですか?あるいは私が何か間違っているとしたら?

答えて

1

はい、これによりリークが発生します。

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

[[UIDynamicAnimator alloc] initWithReferenceView:self.view] 1参照カウントを持つオブジェクトを返します。問題は、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]; 

または円弧に変換します!それはあなたのためにすべてこれをしたでしょう。

+0

あなたはそうです。その人にビールをください! 'autorelease'を 'self.animator'と共に使用するとメモリリークが修正されました。私はautoreleasing 'UISnapBehavior'を試みたが、 'self.animator'は試みなかった。そしてあなたの説明は、私が何が欠けていたかを理解する助けになりました。私は作業コードを追加し、これを解決策としてマークしました。 – Greg

関連する問題