zoukankan      html  css  js  c++  java
  • 使用到定时器,单例和协议的一个小应用(2 )

        上一篇文章写了一个简单的定时器,也可以正常的运行了。但是现在有一个问题,就是如果像我们手机上那个定时器程序一样。即使切换到闹钟或者世界时间的时候定时器依然要要在后在运行。我们刚才那种写法就并不行了。因为我们当我们转换其他界面的时候,已经退出了那个定时器的界面,意味着那个界面的Controller已经被销毁了。我们的定时器并不能在我们切换到其他界面的时候依然运行。这个时候需要一个怎样的方法来解决啦。我们就要用到一个在很多语言下都有的模式叫单例模式。

        首先最重要的问题时搞懂什么叫做单例模式。在网上查了很多资料,都看的不是很懂,现在我说一下我自己的理解。单例是一个跟程序的运行的周期一样的类。一个程序里面只能有一个单例类的实例。你现在有个controller,你在里面实例化了一个单例,你在这个controller中修改了这个实例的属性的值。现在有另外一个controller1。你在这个类中继续实例化了一个单例。你查看这个实例属性的值,你会发现跟刚才你修改过后的属性的值一样。而且单例生命周期是跟程序生命周期一样,所以当你退出了那个界面之后 你会发现定时器依然在后台运行。

    所以我们想使定时器在我们退出那个界面之后还能继续运行,我们就需要创造一个单例类。

    下面贴出单例类的代码

    Timemanager.h 文件

    #import <Foundation/Foundation.h>

    #import "Time.h"

      

     

    @interface Timemanage : NSObject

     

    @property(nonatomic,strong) Time *time;

     

    +(Timemanage*)shareManage;//单例类的类初始化方法,十分重要,决定了你这个类是否是单例类

     

     

    -(void)timestart;

     

    -(void)timepause;

     

     

    @end

     

     

    Timemanage.m文件

    #import "Timemanage.h"

     

    @interface Timemanage()

     

    @property(nonatomic,retain)NSTimer *timer;

     

    @end

     

     

    @implementation Timemanage

     

     

    +(Timemanage*)shareManage;//单例的初始化方法,有很多种,但是这个是苹果官方推荐的。

    {

        static Timemanage *timemanageInstance=nil;

        static dispatch_once_t predicate;

        dispatch_once(&predicate, ^{

            timemanageInstance=[[self alloc]init];

        });

        return  timemanageInstance;

    }

     

    -(void)timestart

    {

        if (!_timer) {

            _timer=[NSTimer scheduledTimerWithTimeInterval:0.01f target:self selector:@selector(UpdateUI) userInfo:nil repeats:YES];

        }

    }

     

    -(void)timepause

    {

        if (_timer.valid) {

            [_timer invalidate];

        }

        _timer=nil;

    }

     

    -(void)UpdateUI

    {

        self.time.ms++;

        [self.time changtime];

      //  [self.changedelegate changeUIwithtimestring:[self.time timestring]];会使用到的协议

    }

     

    -(Time*)time

    {

        if (!_time) {

            _time=[[Time alloc]init];

        }

        return _time;

    }

     @end

    我们要的单例已经创建成功了。但是现在问题是怎么才能把我们的时间实时同步到我们的UI上面,刚才没用到单例的时候,我们可以直接在controller中初始化我们的NSTimer,并且在在UPdateUI方法中实时更新我们的UI,但是现在我们并不能直接引用lable了。所以在这里我们必须使用协议以保证我们的UI与数据同步。

     

     

     首先修改下我们的Timemanage.h文件,在这个文件中创建我们的协议

     

     

    #import <Foundation/Foundation.h>

    #import "Time.h"

     

    @protocol changeUIdelegate <NSObject>

     

    -(void)changeUIwithtimestring:(NSString*)time;//创建协议

     

    @end

     

     

    @interface Timemanage : NSObject

     

    @property(nonatomic,strong) Time *time;

     

    @property(nonatomic,retain) id<changeUIdelegate> changedelegate;//设置协议

     

    +(Timemanage*)shareManage;

     

    -(void)timestart;

     

    -(void)timepause;

     

     

    @end

    现在只需要在Timemanage.m中添加一句话

     

    把UpdateUI方法修改一下

    -(void)UpdateUI

    {

        self.time.ms++;

        [self.time changtime];

        [self.changedelegate changeUIwithtimestring:[self.time timestring]];//委托,这个方法调用的时候,viewcontroller的实现协议的方法也会调用。

    }

     

    贴一下viewcontroller的代码

     

    #import "ViewController.h"

    #import "Timemanage.h"

     

    @interface ViewController ()<changeUIdelegate>//声明实现了协议

    @property (weak, nonatomic) IBOutlet UILabel *lable;

     

    @property(strong,nonatomic) Timemanage *time;

     

    @end

     

    @implementation ViewController

     

    - (void)viewDidLoad {

        [super viewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

    }

     

    - (void)didReceiveMemoryWarning {

        [super didReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

    }

    - (IBAction)start:(id)sender {

        

        _time=[Timemanage shareManage];

        _time.changedelegate=self;//把委托对象设为自己

        [_time  timestart];

        

    }

     

     

    -(void)changeUIwithtimestring:(NSString *)time

    {

        self.lable.text=time;//协议的实现,将传过来的time显示在lable。

    }

     

    - (IBAction)stop:(id)sender {

        [_time timepause];

    }

    现在大家可以添加个viewtroller2,然后切换到另外一个界面,再切换到计时器页面,会发现计时器依然在运行。

     

     

     第一次写博客,有很多东西表达不是很清楚。希望能指出。

     

    @end

  • 相关阅读:
    Argument 1 cannot be null
    灵性的笔尖勾勒幻想的国度,找寻梦想的脚步!用我的思想创建一个芬芳的世界!
    错误: Aggregate query has too many rows > 不需要用子查询
    之前玩GAE收藏夹里的链接
    ExtJs收缩按钮相应事件如何被捕捉?
    winxp注册表之开始菜单和任务栏
    C#代码规范 程序员必备的秘笈[转]
    c#中datagridview里checkbox的使用方法[转]
    Log4Net详细介绍[转]
    Ubuntu10.04窗口风格改为windows风格的方法
  • 原文地址:https://www.cnblogs.com/xiaomingtongxue/p/4440171.html
Copyright © 2011-2022 走看看