在后臺(tái)執(zhí)行短信驗(yàn)證碼倒計(jì)時(shí)

前言

我們一般做的短信驗(yàn)證碼功能哈恰,應(yīng)用在前臺(tái)運(yùn)行的時(shí)候,肯定是沒有問題的臼氨,但是點(diǎn)擊一下Home鍵進(jìn)入后臺(tái)掛起的狀態(tài)掺喻,我們的定時(shí)器就停止了。

網(wǎng)上很多說記錄什么進(jìn)入后臺(tái)的時(shí)間储矩,我覺的那太費(fèi)事了感耙,我們完全可以通過申請(qǐng)應(yīng)用在后臺(tái)執(zhí)行來執(zhí)行我們的倒計(jì)時(shí)。

1持隧、先放我們倒計(jì)時(shí)的代碼即硼,這段代碼在模擬器運(yùn)行是沒有問題的,但是在真機(jī)進(jìn)入掛起狀態(tài)會(huì)停止

<pre>

  • (void)sentPhoneCodeTimeMethod {
    //倒計(jì)時(shí)時(shí)間 - 60S
    __block NSInteger timeOut = 59;
    //執(zhí)行隊(duì)列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //計(jì)時(shí)器 -》 dispatch_source_set_timer自動(dòng)生成
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);

    dispatch_source_set_event_handler(timer, ^{
    if (timeOut <= 0) {
    dispatch_source_cancel(timer);
    //主線程設(shè)置按鈕樣式
    dispatch_async(dispatch_get_main_queue(), ^{
    // 倒計(jì)時(shí)結(jié)束
    [self.captchaButton setBackgroundImage:kImage(kCaptchaButtonNormal) forState:UIControlStateNormal];
    [self.captchaButton setTitle:kCaptchaButtonTitle forState:UIControlStateNormal];
    [self.captchaButton setEnabled:YES];

              [self.captchaButton setUserInteractionEnabled:YES];
              
          });
      } else {
          //開始計(jì)時(shí)
          //剩余秒數(shù) seconds
          NSInteger seconds = timeOut % 60;
          NSString *strTime = [NSString stringWithFormat:@"%.1ld", seconds];
          //主線程設(shè)置按鈕樣式
          dispatch_async(dispatch_get_main_queue(), ^{
              [UIView beginAnimations:nil context:nil];
              [UIView setAnimationDuration:1.0];
              
              [self.captchaButton setBackgroundImage:kImage(kCaptchaButtonSelected) forState:UIControlStateNormal];
              NSString *title = [NSString stringWithFormat:@"%@ s",strTime];
              [self.captchaButton setTitle:title forState:UIControlStateNormal];
              
              [UIView commitAnimations];
              //計(jì)時(shí)器件不允許點(diǎn)擊
              [self.captchaButton setUserInteractionEnabled:NO];
              
          });
          timeOut--;
          
      }
    

    });
    dispatch_resume(timer);
    }
    </pre>

2屡拨、下面是我們用到的一個(gè)小技巧

一般來說只酥,如果不進(jìn)行后臺(tái)申請(qǐng)褥实,在iOS系統(tǒng)上,當(dāng)應(yīng)用退到后臺(tái)后裂允,只有5s的時(shí)間去執(zhí)行代碼损离,之后將進(jìn)入掛起狀態(tài)。只有像音頻播放绝编、定位草冈、newsstand、VoIP等功能才能持續(xù)在后臺(tái)運(yùn)行瓮增。但是開發(fā)其它應(yīng)用是我們可以通過申請(qǐng)后臺(tái)怎棱,來獲得3分鐘的后臺(tái)執(zhí)行代碼時(shí)間(iOS7以前是10分鐘)。

所以我們決定申請(qǐng)3分鐘來執(zhí)行我們1分鐘的倒計(jì)時(shí)代碼:
<pre>

import "AppDelegate.h"

@interface AppDelegate (){
NSInteger count;
}
@property(strong, nonatomic)NSTimer *mTimer;
@property(assign, nonatomic)UIBackgroundTaskIdentifier backIden;

@end

@implementation AppDelegate

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    count=0;
    return YES;
    }

  • (void)applicationDidEnterBackground:(UIApplication *)application {
    _mTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_mTimer forMode:NSRunLoopCommonModes];
    [self beginTask];
    }

  • (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"進(jìn)入前臺(tái)");
    [self endBack];
    }

//計(jì)時(shí)
-(void)countAction{
NSLog(@"%li",count++);
}

//申請(qǐng)后臺(tái)
-(void)beginTask
{
NSLog(@"begin=============");
_backIden = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
//在時(shí)間到之前會(huì)進(jìn)入這個(gè)block绷跑,一般是iOS7及以上是3分鐘拳恋。按照規(guī)范,在這里要手動(dòng)結(jié)束后臺(tái)砸捏,你不寫也是會(huì)結(jié)束的(據(jù)說會(huì)crash)
NSLog(@"將要掛起=============");
[self endBack];
}];
}

//注銷后臺(tái)
-(void)endBack
{
NSLog(@"end=============");
[[UIApplication sharedApplication] endBackgroundTask:_backIden];
_backIden = UIBackgroundTaskInvalid;
}

@end
</pre>

這樣就輕松谬运、完美解決了我們的需求了!?巡亍梆暖!

3、 擴(kuò)充無限倒計(jì)時(shí)

慎用掂骏!因?yàn)檫@個(gè)需要申請(qǐng)后臺(tái)播放音頻的權(quán)限轰驳。如果你的應(yīng)用不是相關(guān)應(yīng)用,AppStore審核可能不會(huì)通過弟灼。

先在我們的info.plist文件配置中级解,添加一行,如下兩個(gè)屬性:

Required background modes
App plays audio or streams audio/video using AirPlay

配置信息.png

AppDelegate.m文件中代碼還是和上面一樣田绑,設(shè)置 UIBackgroundTaskIdentifier
<pre>

import "AppDelegate.h"

@interface AppDelegate (){
NSInteger count;
}
@property(strong, nonatomic)NSTimer *mTimer;
@property(assign, nonatomic)UIBackgroundTaskIdentifier backIden;

@end

@implementation AppDelegate

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    count=0;
    return YES;
    }

  • (void)applicationDidEnterBackground:(UIApplication *)application {
    _mTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_mTimer forMode:NSRunLoopCommonModes];
    [self beginTask];
    }

  • (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"進(jìn)入前臺(tái)");
    [self endBack];
    }

//計(jì)時(shí)
-(void)countAction{
NSLog(@"%li",count++);
}

//申請(qǐng)后臺(tái)
-(void)beginTask
{
NSLog(@"begin=============");
_backIden = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

    NSLog(@"將要掛起=============");
    [self endBack];
}];

}

//注銷后臺(tái)
-(void)endBack
{
NSLog(@"end=============");
[[UIApplication sharedApplication] endBackgroundTask:_backIden];
_backIden = UIBackgroundTaskInvalid;
}

@end
</pre>

在我們需要后臺(tái)運(yùn)行的控制器中勤哗,例如ViewController.m
<pre>

import "ViewController.h"

import <AVFoundation/AVFoundation.h>

@interface ViewController ()

@property(strong, nonatomic)AVAudioPlayer *mPlayer;

@property(assign, nonatomic)CGFloat mCount;

@end

@implementation ViewController

  • (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    _mCount = 0;

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(countTime) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    }

-(void)countTime{
_mCount+=10;
NSLog(@"%f",_mCount);

if ([[UIApplication sharedApplication] backgroundTimeRemaining] < 60.) {//當(dāng)剩余時(shí)間小于60時(shí),開如播放音樂掩驱,并用這個(gè)假前臺(tái)狀態(tài)再次申請(qǐng)后臺(tái)
    NSLog(@"播放%@",[NSThread currentThread]);
    [self playMusic];
    //申請(qǐng)后臺(tái)
    [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"我要掛起了");
    }];
}

}

-(void)playMusic{
//1.音頻文件的url路徑芒划,實(shí)際開發(fā)中,用無聲音樂
NSURL *url=[[NSBundle mainBundle]URLForResource:@"歡沁.mp3" withExtension:Nil];

//2.創(chuàng)建播放器(注意:一個(gè)AVAudioPlayer只能播放一個(gè)url)
_mPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:Nil];

//3.緩沖
[_mPlayer prepareToPlay];

//4.播放
[_mPlayer play];

}

@end
</pre>

完欧穴。

自助者民逼,天助之。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末苔可,一起剝皮案震驚了整個(gè)濱河市缴挖,隨后出現(xiàn)的幾起案子袋狞,更是在濱河造成了極大的恐慌焚辅,老刑警劉巖映屋,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異同蜻,居然都是意外死亡棚点,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門湾蔓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘫析,“玉大人,你說我怎么就攤上這事默责”嵫” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵桃序,是天一觀的道長(zhǎng)杖虾。 經(jīng)常有香客問我,道長(zhǎng)媒熊,這世上最難降的妖魔是什么奇适? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮芦鳍,結(jié)果婚禮上嚷往,老公的妹妹穿的比我還像新娘。我一直安慰自己柠衅,他們只是感情好皮仁,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著菲宴,像睡著了一般魂贬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上裙顽,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天付燥,我揣著相機(jī)與錄音,去河邊找鬼愈犹。 笑死键科,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的漩怎。 我是一名探鬼主播勋颖,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼勋锤!你這毒婦竟也來了饭玲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤叁执,失蹤者是張志新(化名)和其女友劉穎茄厘,沒想到半個(gè)月后矮冬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡次哈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年胎署,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窑滞。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡琼牧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哀卫,到底是詐尸還是另有隱情巨坊,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布此改,位于F島的核電站抱究,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏带斑。R本人自食惡果不足惜鼓寺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望勋磕。 院中可真熱鬧妈候,春花似錦、人聲如沸挂滓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赶站。三九已至幔虏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贝椿,已是汗流浹背想括。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留烙博,地道東北人瑟蜈。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像渣窜,于是被迫代替她去往敵國和親铺根。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,522評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理乔宿,服務(wù)發(fā)現(xiàn)位迂,斷路器,智...
    卡卡羅2017閱讀 134,601評(píng)論 18 139
  • IOS開發(fā)之----詳解在IOS后臺(tái)執(zhí)行 文一 我從蘋果文檔中得知,一般的應(yīng)用在進(jìn)入后臺(tái)的時(shí)候可以獲取一定時(shí)間來...
    dongfang閱讀 1,379評(píng)論 0 7
  • 自從古老的iOS4以來,當(dāng)用戶點(diǎn)擊home建的時(shí)候,你可以使你的APP們?cè)趦?nèi)存中處于suspended(掛起)狀態(tài)...
    木易林1閱讀 3,045評(píng)論 1 4
  • 有許多想做的事情掂林,包括已經(jīng)在做的了和存留在想法中的臣缀,例如跳拉丁、例如寫公眾號(hào)党饮、例如在豆瓣發(fā)布活動(dòng)、例如去找認(rèn)為有趣...
    黑眼圈圈閱讀 187評(píng)論 0 0