Ios6 IOS对象在我将其ID设置为nil后在计时器上重新启动

Ios6 IOS对象在我将其ID设置为nil后在计时器上重新启动,ios6,timer,null,Ios6,Timer,Null,DemoViewController负责向用户显示教程。包含动画和计时器,可在用户忽略时重复手势演示。是从DataViewController实例化的。为零,但随后在其内部计时器上重新启动。我需要它完全消失,这样当用户返回到第一页时就不会再次创建它 dataViewController.h #import "DemoViewController.h" @property (strong,nonatomic) DemoViewController *demoController; -(void)

DemoViewController负责向用户显示教程。包含动画和计时器,可在用户忽略时重复手势演示。是从DataViewController实例化的。为零,但随后在其内部计时器上重新启动。我需要它完全消失,这样当用户返回到第一页时就不会再次创建它

dataViewController.h

#import "DemoViewController.h"
@property (strong,nonatomic) DemoViewController *demoController;
-(void) viewWillAppear:(BOOL)animated {
    // demoPageNumber is 0
    if ((self.demoController== nil) && ([_pageNumber isEqualToNumber:demoPageNumber])){
       self.demoController = [[DemoViewController alloc] initWithView:self.view];
    }
}

-(void) viewWillDisappear:(BOOL)animated{
    [self.demoController free]; // invalidate timer, nil all internal objects
    self.demoController=nil; // should free object
}
dataViewController.h

#import "DemoViewController.h"
@property (strong,nonatomic) DemoViewController *demoController;
-(void) viewWillAppear:(BOOL)animated {
    // demoPageNumber is 0
    if ((self.demoController== nil) && ([_pageNumber isEqualToNumber:demoPageNumber])){
       self.demoController = [[DemoViewController alloc] initWithView:self.view];
    }
}

-(void) viewWillDisappear:(BOOL)animated{
    [self.demoController free]; // invalidate timer, nil all internal objects
    self.demoController=nil; // should free object
}
DemoViewController.m

-(void) free{
   [animationRespawnTimer invalidate];
   animationRespawnTimer=nil;
}

-(void) respawnDemoWithSelector:(SEL)selector{
    NSLog(@"Timer fired %@", self);
    [self resetTimer];
    animationRespawnTimer = [NSTimer scheduledTimerWithTimeInterval:10
                                                        target:self
                                                      selector:selector
                                                      userInfo:nil
                                                       repeats:NO];
}

-(void) showScrollDemo{


    NSLog(@"showScrollDemo fired");
    [self stopPreviousAnimations];
    scrollHandView.frame = CGRectMake(315.0, 700.0, 100, 100);
    scrollHandView.hidden=NO;
    scrollHandView.alpha=1;

    [UIView animateWithDuration:3.0
                          delay: 0.0
                        options: (UIViewAnimationOptionCurveEaseOut |
                                  UIViewAnimationOptionRepeat )
                     animations:^{

                         [UIView setAnimationRepeatCount:3];
                         scrollHandView.frame = CGRectMake(315.0, 300.0, 100, 100);

                     }
                     completion:^(BOOL finished){

                         [UIView animateWithDuration:1.0 delay:0 
                        options:UIViewAnimationOptionCurveEaseOut
                                      animations:^{
                                          scrollHandView.alpha=0;

                          }
                            completion:^(BOOL finished){
                            scrollHandView.hidden=YES;

                    [self respawnDemoWithSelector: @selector(showScrollDemo)];

                          }
                      ];

                 }
 ];
}

加载页面时,如果这是第一个页面,则会实例化demoController,并在清理后退出页面时禁用(自定义自由方法)。根据我的理解,这应该删除demoController对象及其所有内容,包括计时器。调试区域正好显示了这一点!直到在新页面上,demoController计时器神秘地从没有对象ID的地方复活

17:59:14.041 viewWillAppear begin (self.demoController null)
18:00:05.346 viewWillAppear, <DemoViewController: 0x7580310> //demoController created
18:00:15.786 in the demoController method the "showScrollDemo" is fired
18:00:19.834 viewWillAppear end <DemoViewController: 0x7580310>
17:59:14.041视图将显示开始(self.demoController null)
18:00:05.346将显示视图,//已创建demoController
18:00:15.786在demoController方法中,“showScrollDemo”被触发
18:00:19.834视图将显示结束
页面已加载,演示执行良好。现在我正在翻页。ViewWillEnglish事件被激发

18:01:17.966 viewWillDisappear begin, send "free" message to demoController 
18:01:17.966 "free" was performed from <DemoViewController: 0x7580310>
18:01:34.059 viewWillDisappear end (self.demoController null)
18:01:17.966视图将消失。开始时,向demoController发送“免费”消息
18:01:17.966“自由”是从
18:01:34.059 VIEWWILLEND(self.demoController null)
因此,“self.demoController”为空。然后,demoController使用以前的ID重新启动自己

18:02:36.514 Timer fired <DemoViewController: 0x7580310>
18:02:36.514定时器启动

为什么??计时器无法重新启动,它被设置为repeats:NO.

我假设是动画的完成块调用了
respawnDemoWithSelector
,并创建了一个新的计时器

根据这个答案:,你可以停止所有的跑步 动画与

[self.view.layer removeAllAnimations];
或者,您可以将布尔属性
done
添加到已设置的DemoViewController 在
free
方法中选择
YES
,并在动画的完成块中选中:

if (!self.done)
    [self respawnDemoWithSelector: @selector(showScrollDemo)];
更新:动画块捕获对
自身的强引用,从而防止
无法释放该对象。“保留周期”问题的标准解决方案
(假设您使用ARC)是使用对self的弱引用。看起来是这样的:

__weak typeof(self) weakSelf = self;
[UIView animateWithDuration:3.0
                      delay: 0.0
                    options: (UIViewAnimationOptionCurveEaseOut |
                              UIViewAnimationOptionRepeat )
                 animations:^{

                     [UIView setAnimationRepeatCount:3];
                     weakSelf.scrollHandView.frame = CGRectMake(315.0, 300.0, 100, 100);

                 }
                 completion:^(BOOL finished){

                     [UIView animateWithDuration:1.0 delay:0
                                         options:UIViewAnimationOptionCurveEaseOut
                                      animations:^{
                                          weakSelf.scrollHandView.alpha=0;

                                      }
                                      completion:^(BOOL finished){
                                          weakSelf.scrollHandView.hidden=YES;
                                          [weakSelf respawnDemoWithSelector: @selector(showScrollDemo)];

                                      }
                      ];

                 }
 ];
weakSelf
不包含对DemoViewController的强引用,并设置为
nil

如果它指向的对象被解除分配,则自动执行此操作。在这种情况下,发送到块内的
weakSelf
的所有消息都不起任何作用。

是的,动画在被调用的方法中,但如果对象为零,我如何仍然访问其方法?我实例化DemoViewController,调用其方法“showScrollDemo”。然后我将对象置零,并调用该方法。它应该返回nil并且什么也不做,对吗?@JanisJakaitis:但是动画块捕获了对
self
的引用,因此它不会被释放,即使您调用
self.demoController=nil
。至少我是这么想的。你试过我的建议了吗?[self.view.layer removeAllAnimations];没有任何改变。“完成”是一个解决办法,我想找到一种方法,杀死动画和定时器内的“免费”方法。将系统恢复到以前的状态,此时demoController尚未实例化。@JanisJakaitis:对self的弱引用可能是解决方案。稍后将更新答案,目前正在电话上书写。@JanisJakaitis:我已经更新了答案,希望现在能有所帮助。