NSTimer和NSNotification小结

原创 2013年12月03日 16:25:05

最近在写的一段代码,是由某个组件执行一系列初始化脚本,每个脚本完成后,通知Controller刷新进度条。全部完成以后,通知Controller跳转

其中用到了模板方法模式,在另一篇博客里已经总结过了:在objective-c中实现模板方法模式

另外,原来写的代码有问题,类似:

for(int i = 0; i<[scripts count]; i++){
    // 依次调用脚本的doInit()方法
}

-(void) doInit
{
    // 逻辑处理
    // 通知Controller刷新进度条
}

这段代码没有成功,不知道为什么进度条毫无反应,等到全部脚本都执行完以后,才会一次性刷到头。在网上搜索了一番,发现用NSTimer类设置一个延时就可以解决这个问题。另外消息传递的方式,也从直接调用方法,改成了IOS中的Notification方式。本文总结一下这2方面的内容,以后可以直接拷贝继续用

NSTimer

直接上代码,再解释一下参数:

- (void) runInitScripts
{
    YLSClientInfo *clientInfo = [YLSClientInfo new];
    // 用NSTimer来延时执行,否则Bootstrap View Controller里的进度条刷新失败,原因不明
    [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(doRun:) userInfo:clientInfo repeats:YES];
}

-(void) doRun:(NSTimer*) timer
{
    if(doneSteps < maxSteps){
        [[scripts objectAtIndex:doneSteps] doInit:timer.userInfo];// 脚本未执行完,执行下一个脚本
    }else{
        // 脚本执行完毕,注销Timer,发送初始化完成通知
        [timer invalidate];
    }
}

代码包括2部分,scheduledTimerWithTimeInterval方法是注册一个定时任务,类似setTimeInterval(),其中参数的含义如下:

interval:延时,单位是秒,如果小于或等于0,会被设置为0.1

target:触发时调用哪个实例上的方法,一般就设置为self

selector:触发时调用的方法。这个方法的声明有讲究,后面会说

userInfo:如果需要传参,就写在这个参数里

repeats:如果设置为YES,就会反复执行,直到被注销;否则只执行一次


然后需要定义一个函数,来被前面的Timer触发,也就是第3个参数。这个函数返回值必须是void,只能接受一个NSTimer的指针作为参数

实际被调用时,这个参数会是Timer自己,然后调用timer.userInfo,就可以拿到设置Timer时的第4个参数。不需要做类型转换

通知机制

IOS中的通知是通过NSNotificationCenter这个类实现的,示例代码如下。下文的“事件”和“通知”是同义词

首先是注册通知侦听器:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(listenStepDoneEvent:) name:STEP_DONE object:initialOperator];

参数的含义如下:

observer:事件发生时,调用哪个实例上的方法,一般就是self

selector:事件发生时,将会调用的函数。和NSTimer一样,这个函数的定义也是有要求的,后面会说

name:事件的名称,就是一个字符串,比如@"someEvent"这样,当这个事件发生时,才会触发侦听器

object:发送事件的实例,可以设置为nil。如果设置为nil,那么无论什么实例发的通知,都会被响应;否则只有设置的对象发的通知才会被响应。网上很多文章都把这个参数当成selector函数的参数,其实不是的,可能API变过


注册了通知侦听器,下面是发送通知的代码,已经考虑了需要传参的场景:

NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:
                          stepMsg, @"content", [NSNumber numberWithFloat:currentProgress], @"stage", nil];// KEY在后面,VALUE在前面
[[NSNotificationCenter defaultCenter] postNotificationName:STEP_DONE object:self userInfo:dict];

第二行才是发送通知的代码,但是为了要传参,在第一行组织了一下参数。各参数的含义是:

name:该通知的名称,和注册侦听器时的name参数对应

object:谁发送的通知,一般都设置成self,和注册侦听器时的object参数对应

userInfo:如果要传参,就设置为要传的参数;如果不需要传参,可以设置为nil

上面的userInfo似乎和NSTimer里很像,不过还是有点区别,这里的userInfo必须是NSDictionary类型,而Timer里的userInfo可以是任意类型。另外,组织NSDictionary对象时,注意KEY在后面,VALUE在前面。。。这和javascript与java里的API是相反的


然后是事件触发时要调用的函数定义:

// 响应单个初始化脚本完成事件
-(void) listenStepDoneEvent:(NSNotification*) notification
{
    NSNumber* stage = [notification.userInfo objectForKey:@"stage"];
    NSString* content = [notification.userInfo objectForKey:@"content"];
    [self refreshProgressTo:[stage floatValue] WithContent:content];
}

这个函数是在注册侦听器的时候的第2个参数,返回值必须是void,接收一个NSNotification类型的参数。通过notification.userInfo,可以取到发送通知时设置的userInfo,通过这种方式来传参。不过前面说过,userInfo的类型规定是NSDictionary,不能是自定义类型,所以没有Timer的方法那么方便


最后是注销侦听器的方法,记得在最后合适的地方要调用一下:

[[NSNotificationCenter defaultCenter] removeObserver:self];// 初始化完成,移除所有Listener

这个方法会移除self的所有侦听器,还有一个更细粒度的API,可以指定移除对具体某个事件,或者某个来源的侦听,文档里有

版权声明:本文为博主原创文章,未经博主允许不得转载。

iOS-NSTimer定时器总结

先写一个小例子,然后再来深层析挖掘,本文有部分借鉴网上和官方现有文档 上代码 #import "ViewController.h" @interface ViewController () { ...
  • JackJia2015
  • JackJia2015
  • 2016年01月27日 16:42
  • 1651

iOS多线程的初步研究(四)-- NSTimer

原文地址  http://www.cnblogs.com/sunfrog/p/3243230.html 理解run loop后,才能彻底理解NSTimer的实现原理,也就是说...
  • lengshengren
  • lengshengren
  • 2013年10月21日 10:38
  • 8785

iOS----NSTimer的使用小结

1. NSRunLoopCommonModes和Timer     当使用NSTimer的scheduledTimerWithTimeInterval方法时。事实上此时Timer会被加入到当前线程的...
  • wwwang89123
  • wwwang89123
  • 2014年01月12日 20:55
  • 1128

delegate、NSNotification、block比较

  • 2015年05月20日 16:52
  • 123KB
  • 下载

NSTimer定时器

  • 2016年01月27日 16:34
  • 301KB
  • 下载

【OC学习-34】通知NSNotification,类似于KVO,用于对象之间监听然后发通知提醒

通知其实和KVO类似,就是先在类A中设置通知,然后再类B中设置个监听这个通知的方法,当然可以通过这个通知方法可以传递一些参数,得到这个参数之后,一般是触发一个动作,此处举例就是触发输出一些内容而已。...
  • wsb200514
  • wsb200514
  • 2014年09月10日 16:32
  • 1603

NSNotification多次执行的问题

本文主要讲述在iOS开发过程中, 有关于NSNnotification的使用相关的问题, 问题主要源于我在项目开发中, 监听键盘显示和关闭的相关通知, 发现通知方法会被多次执行, 因为有很多地方会注册...
  • wlaizff
  • wlaizff
  • 2016年07月22日 14:38
  • 2489

iOS开发学习专题-基础知识(五) NSDate时间 NSUserDefaults本地存储 NSNotification系统通知的详细使用方式

本文主要讲解的是 NSDate时间、NSUserDefaults本地存储、NSNotification系统通知的详细使用方式,也是NS系列基础知识的最后一篇文章 文章是博主原创,转载请标明出处 NSU...
  • werctzzz
  • werctzzz
  • 2017年05月24日 18:33
  • 1320

iOS 通知的使用NSNotification的使用

说明:倘若在一个雷中想要执行另一个类中的方法可以使用通知 1.创建一个通知对象: 使用notificationWithName:object:或者 notificationWithName:obje...
  • bestoneToo
  • bestoneToo
  • 2015年11月02日 17:22
  • 227

iOS雨笙 NSNotification通知模式的原理及实现

NSNotification(通知模式),是界面间通信的一种方式. 这种模式的实现,是通过某一个界面去发送通知,其它任意数量的对象只要遵循某一种原则,都可以接收到这个通知消息.即使这些对象之间没有耦合...
  • ys1037245421
  • ys1037245421
  • 2015年09月28日 19:19
  • 1998
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:NSTimer和NSNotification小结
举报原因:
原因补充:

(最多只允许输入30个字)