使用到定時器,單例和協議的一個小應用(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