上一篇文章寫了一個(gè)簡(jiǎn)單的定時(shí)器,也可以正常的運(yùn)行了。但是現(xiàn)在有一個(gè)問題,就是如果像我們手機(jī)上那個(gè)定時(shí)器程序一樣。即使切換到鬧鐘或者世界時(shí)間的時(shí)候定時(shí)器依然要要在后在運(yùn)行。我們剛才那種寫法就并不行了。因?yàn)槲覀儺?dāng)我們轉(zhuǎn)換其他界面的時(shí)候,已經(jīng)退出了那個(gè)定時(shí)器的界面,意味著那個(gè)界面的Controller已經(jīng)被銷毀了。我們的定時(shí)器并不能在我們切換到其他界面的時(shí)候依然運(yùn)行。這個(gè)時(shí)候需要一個(gè)怎樣的方法來解決啦。我們就要用到一個(gè)在很多語言下都有的模式叫單例模式。
首先最重要的問題時(shí)搞懂什么叫做單例模式。在網(wǎng)上查了很多資料,都看的不是很懂,現(xiàn)在我說一下我自己的理解。單例是一個(gè)跟程序的運(yùn)行的周期一樣的類。一個(gè)程序里面只能有一個(gè)單例類的實(shí)例。你現(xiàn)在有個(gè)controller,你在里面實(shí)例化了一個(gè)單例,你在這個(gè)controller中修改了這個(gè)實(shí)例的屬性的值?,F(xiàn)在有另外一個(gè)controller1。你在這個(gè)類中繼續(xù)實(shí)例化了一個(gè)單例。你查看這個(gè)實(shí)例屬性的值,你會(huì)發(fā)現(xiàn)跟剛才你修改過后的屬性的值一樣。而且單例生命周期是跟程序生命周期一樣,所以當(dāng)你退出了那個(gè)界面之后 你會(huì)發(fā)現(xiàn)定時(shí)器依然在后臺(tái)運(yùn)行。
所以我們想使定時(shí)器在我們退出那個(gè)界面之后還能繼續(xù)運(yùn)行,我們就需要?jiǎng)?chuàng)造一個(gè)單例類。
下面貼出單例類的代碼
Timemanager.h 文件
#import <Foundation/Foundation.h>
#import "Time.h"
@interface Timemanage : NSObject
@PRoperty(nonatomic,strong) Time *time;
+(Timemanage*)shareManage;//單例類的類初始化方法,十分重要,決定了你這個(gè)類是否是單例類
-(void)timestart;
-(void)timepause;
@end
Timemanage.m文件
#import "Timemanage.h"
@interface Timemanage()
@property(nonatomic,retain)NSTimer *timer;
@end
@implementation Timemanage
+(Timemanage*)shareManage;//單例的初始化方法,有很多種,但是這個(gè)是蘋果官方推薦的。
{
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]];會(huì)使用到的協(xié)議
}
-(Time*)time
{
if (!_time) {
_time=[[Time alloc]init];
}
return _time;
}
@end
我們要的單例已經(jīng)創(chuàng)建成功了。但是現(xiàn)在問題是怎么才能把我們的時(shí)間實(shí)時(shí)同步到我們的UI上面,剛才沒用到單例的時(shí)候,我們可以直接在controller中初始化我們的NSTimer,并且在在UPdateUI方法中實(shí)時(shí)更新我們的UI,但是現(xiàn)在我們并不能直接引用lable了。所以在這里我們必須使用協(xié)議以保證我們的UI與數(shù)據(jù)同步。
首先修改下我們的Timemanage.h文件,在這個(gè)文件中創(chuàng)建我們的協(xié)議
#import <Foundation/Foundation.h>
#import "Time.h"
@protocol changeUIdelegate <NSObject>
-(void)changeUIwithtimestring:(NSString*)time;//創(chuàng)建協(xié)議
@end
@interface Timemanage : NSObject
@property(nonatomic,strong) Time *time;
@property(nonatomic,retain) id<changeUIdelegate> changedelegate;//設(shè)置協(xié)議
+(Timemanage*)shareManage;
-(void)timestart;
-(void)timepause;
@end
現(xiàn)在只需要在Timemanage.m中添加一句話
把UpdateUI方法修改一下
-(void)UpdateUI
{
self.time.ms++;
[self.time changtime];
[self.changedelegate changeUIwithtimestring:[self.time timestring]];//委托,這個(gè)方法調(diào)用的時(shí)候,viewcontroller的實(shí)現(xiàn)協(xié)議的方法也會(huì)調(diào)用。
}
貼一下viewcontroller的代碼
#import "ViewController.h"
#import "Timemanage.h"
@interface ViewController ()<changeUIdelegate>//聲明實(shí)現(xiàn)了協(xié)議
@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;//把委托對(duì)象設(shè)為自己
[_time timestart];
}
-(void)changeUIwithtimestring:(NSString *)time
{
self.lable.text=time;//協(xié)議的實(shí)現(xiàn),將傳過來的time顯示在lable。
}
- (IBAction)stop:(id)sender {
[_time timepause];
}
現(xiàn)在大家可以添加個(gè)viewtroller2,然后切換到另外一個(gè)界面,再切換到計(jì)時(shí)器頁(yè)面,會(huì)發(fā)現(xiàn)計(jì)時(shí)器依然在運(yùn)行。
第一次寫博客,有很多東西表達(dá)不是很清楚。希望能指出。
@end
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注