上一篇文章寫了一個簡單的定時器,也可以正常的運行了。但是現在有一個問題,就是如果像我們手機上那個定時器程序一樣。即使切換到鬧鐘或者世界時間的時候定時器依然要要在后在運行。我們剛才那種寫法就并不行了。因為我們當我們轉換其他界面的時候,已經退出了那個定時器的界面,意味著那個界面的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
新聞熱點
疑難解答