亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

iOS如何保持程序在后臺長時間運行

 更新時間:2016年09月22日 11:12:58   作者:卟師  
這篇文章主要為大家詳細介紹了iOS如何保持程序在后臺長時間運行,具有一定的參考價值,感興趣的小伙伴們可以參考一下

iOS 為了讓設(shè)備盡量省電,減少不必要的開銷,保持系統(tǒng)流暢,因而對后臺機制采用墓碑式的“假后臺”。除了系統(tǒng)官方極少數(shù)程序可以真后臺,一般開發(fā)者開發(fā)出來的應(yīng)用程序后臺受到以下限制:

1.用戶按Home之后,App轉(zhuǎn)入后臺進行運行,此時擁有180s后臺時間(iOS7)或者600s(iOS6)運行時間可以處理后臺操作

2.當180S或者600S時間過去之后,可以告知系統(tǒng)未完成任務(wù),需要申請繼續(xù)完成,系統(tǒng)批準申請之后,可以繼續(xù)運行,但總時間不會超過10分鐘。

3.當10分鐘時間到之后,無論怎么向系統(tǒng)申請繼續(xù)后臺,系統(tǒng)會強制掛起App,掛起所有后臺操作、線程,直到用戶再次點擊App之后才會繼續(xù)運行。

當然iOS為了特殊應(yīng)用也保留了一些可以實現(xiàn)“真后臺”的方法,摘取比較常用的:

1.VOIP

2.定位服務(wù)

3.后臺下載

4.在后臺一直播放無聲音樂(容易受到電話或者其他程序影響,所以暫未考慮)

5….更多

其中VOIP需要綁定一個Socket鏈接并申明給系統(tǒng),系統(tǒng)將會在后臺接管這個連接,一旦遠端數(shù)據(jù)過來,你的App將會被喚醒10s(或者更少)的時間來處理數(shù)據(jù),超過時間或者處理完畢,程序繼續(xù)休眠。

后臺現(xiàn)在是iOS7引入的新API,網(wǎng)上實現(xiàn)的代碼比較少,博主也沒有細心去找。

由于博主要做的App需要在后臺一直運行,每隔一段時間給服務(wù)器主動發(fā)送消息來保持帳號登陸狀態(tài),因而必須確保App不被系統(tǒng)墓碑限制。

博主最先嘗試了很多方法,包括朋友發(fā)來的一個Demo,每180s后臺時間過期就銷毀自己然后再創(chuàng)建一個后臺任務(wù),但是實際測試只有10分鐘時間。最后因為考慮到VOIP對服務(wù)端改動太大,時間又太緊,所以選擇了定位服務(wù)的方法來保持后臺。

要啟動定位服務(wù):

1.需要引入頭文件:#import

2.在AppDelegate.m中定義CLLocationManager * locationManager;作為全局變量方便控制

3.在程序啟動初期對定位服務(wù)進行初始化:

locationManager = [[CLLocationManager alloc] init];locationManager.delegate =self;
//or whatever class you have for managing location

​4.在程序轉(zhuǎn)入后臺的時候,啟動定位服務(wù)

[locationManager startUpdatingLocation];(第一次運行這個方法的時候,如果之前用戶沒有使用過App,則會彈出是否允許位置服務(wù),關(guān)于用戶是否允許,后面代碼中有判斷)

這樣在定位服務(wù)可用的時候,程序會不斷刷新后臺時間,實際測試,發(fā)現(xiàn)后臺180s時間不斷被刷新,達到長久后臺的目的。

但是這樣使用也有一些問題,在部分機器上面,定位服務(wù)即使打開也可能不能刷新后臺時間,需要完全結(jié)束程序再運行。穩(wěn)定性不知道是因為代碼原因還是系統(tǒng)某些機制原因。

下面貼上代碼:

注意:代碼中包含朋友給的demo中,180s時間后銷毀自己再創(chuàng)建自己的后臺方法,我自己實現(xiàn)過程中加入了定位服務(wù)來確保后臺能夠一直在線。

源碼參考部分來自網(wǎng)上,因為翻了Google,找了很多英文方面的博文,在此感謝原作者分享。

判斷用戶是否打開了定位服務(wù),是否禁用了該程序的定位權(quán)限:

if(![CLLocationManager locationServicesEnabled] || ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied))//判斷定位服務(wù)是否打開
{
   [InterfaceFuncation ShowAlertWithMessage:@"錯誤"AlertMessage:@"定位服務(wù)未打開\n保持在線需要后臺定位服務(wù)\n請到 設(shè)置-隱私 中打開定位服務(wù)"ButtonTitle:@"我錯了"];
   return;
}

​AppDelegate.m源碼:

@property(assign, nonatomic) UIBackgroundTaskIdentifier bgTask;
@property(strong, nonatomic) dispatch_block_t expirationHandler;
@property(assign, nonatomic)BOOL jobExpired;
@property(assign, nonatomic)BOOL background;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
  UIApplication* app = [UIApplication sharedApplication];
  __weak NSUAAAIOSAppDelegate* selfRef =self;
  self.expirationHandler = ^{ //創(chuàng)建后臺自喚醒,當180s時間結(jié)束的時候系統(tǒng)會調(diào)用這里面的方法
    [app endBackgroundTask:selfRef.bgTask];
     selfRef.bgTask = UIBackgroundTaskInvalid;
     selfRef.bgTask = [app beginBackgroundTaskWithExpirationHandler:selfRef.expirationHandler];
     NSLog(@"Expired");
     selfRef.jobExpired =YES;
     while(selfRef.jobExpired)
     {
       // spin while we wait for the task to actually end.
       NSLog(@"等待180s循環(huán)進程的結(jié)束");
       [NSThreadsleepForTimeInterval:1];
     }
     // Restart the background task so we can run forever.
     [selfRef startBackgroundTask];
   };
   // Assume that we're in background at first since we get no notification from device that we're in background when
   // app launches immediately into background (i.e. when powering on the device or when the app is killed and restarted)
   [selfmonitorBatteryStateInBackground];
   locationManager = [[CLLocationManager alloc] init];
   locationManager.delegate =self;
   //[locationManager startUpdatingLocation];
   returnYES;
}
- (void)monitorBatteryStateInBackground
{
   self.background =YES;
   [selfstartBackgroundTask];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
   // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
   NSLog(@"App is active");
   [UIApplication sharedApplication].applicationIconBadgeNumber=0;//取消應(yīng)用程序通知腳標
   [locationManager stopUpdatingLocation];
   self.background =NO;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
   // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
   // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
   //if([self bgTask])
   if(isLogined)//當?shù)顷憼顟B(tài)才啟動后臺操作
   {
      self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:self.expirationHandler];
      NSLog(@"Entered background");
      [selfmonitorBatteryStateInBackground];
    }
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError*)error//當定位服務(wù)不可用出錯時,系統(tǒng)會自動調(diào)用該函數(shù)
{
   NSLog(@"定位服務(wù)出錯");
   if([error code]==kCLErrorDenied)//通過error的code來判斷錯誤類型
   {
      //Access denied by user
      NSLog(@"定位服務(wù)未打開");
      [InterfaceFuncation ShowAlertWithMessage:@"錯誤"AlertMessage:@"未開啟定位服務(wù)\n客戶端保持后臺功能需要調(diào)用系統(tǒng)的位置服務(wù)\n請到設(shè)置中打開位置服務(wù)"ButtonTitle:@"好"];
   }
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray*)locations//當用戶位置改變時,系統(tǒng)會自動調(diào)用,這里必須寫一點兒代碼,否則后臺時間刷新不管用
{
    NSLog(@"位置改變,必須做點兒事情才能刷新后臺時間");
    CLLocation *loc = [locations lastObject];
    //NSTimeInterval backgroundTimeRemaining = [[UIApplication sharedApplication] backgroundTimeRemaining];
    //NSLog(@"Background Time Remaining = %.02f Seconds",backgroundTimeRemaining);
    // Lat/Lon
    floatlatitudeMe = loc.coordinate.latitude;
    floatlongitudeMe = loc.coordinate.longitude;
}
- (void)startBackgroundTask
{
    NSLog(@"Restarting task");
    if(isLogined)//當?shù)顷憼顟B(tài)才進入后臺循環(huán)
    {
      // Start the long-running task.
      NSLog(@"登錄狀態(tài)后臺進程開啟");
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          // When the job expires it still keeps running since we never exited it. Thus have the expiration handler
          // set a flag that the job expired and use that to exit the while loop and end the task.
          NSIntegercount=0;
          BOOLNoticeNoBackground=false;//只通知一次標志位
          BOOLFlushBackgroundTime=false;//只通知一次標志位
          locationManager.distanceFilter = kCLDistanceFilterNone;//任何運動均接受,任何運動將會觸發(fā)定位更新
          locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;//定位精度
          while(self.background && !self.jobExpired)
          {
              NSLog(@"進入后臺進程循環(huán)");
              [NSThreadsleepForTimeInterval:1];
              count++;
              if(count>60)//每60s進行一次開啟定位,刷新后臺時間
              {
                  count=0;
                  [locationManager startUpdatingLocation];
                  NSLog(@"開始位置服務(wù)");
                  [NSThreadsleepForTimeInterval:1];
                  [locationManager stopUpdatingLocation];
                  NSLog(@"停止位置服務(wù)");
                  FlushBackgroundTime=false;
               }
               if(!isLogined)//未登錄或者掉線狀態(tài)下關(guān)閉后臺
               {
                  NSLog(@"保持在線進程失效,退出后臺進程");
                  [InterfaceFuncation ShowLocalNotification:@"保持在線失效,登錄已被注銷,請重新登錄"];
                  [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
                  return;//退出循環(huán)
               }
               NSTimeIntervalbackgroundTimeRemaining = [[UIApplication sharedApplication] backgroundTimeRemaining];
               NSLog(@"Background Time Remaining = %.02f Seconds",backgroundTimeRemaining);
               if(backgroundTimeRemaining<30&&NoticeNoBackground==false)
               {
                   [InterfaceFuncation ShowLocalNotification:@"向系統(tǒng)申請長時間保持后臺失敗,請結(jié)束客戶端重新登錄"];
                   NoticeNoBackground=true;
               }
               //測試后臺時間刷新
               if(backgroundTimeRemaining>200&&FlushBackgroundTime==false)
               {
                  [[NSNotificationCenterdefaultCenter] postNotificationName:@"MessageUpdate"object:@"刷新后臺時間成功\n"];
                  FlushBackgroundTime=true;
                  //[InterfaceFuncation ShowLocalNotification:@"刷新后臺時間成功"];
                }
            }
            self.jobExpired =NO;
         });
     }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:

相關(guān)文章

  • iOS中SQLite使用教程

    iOS中SQLite使用教程

    sqlite是嵌入式的和輕量級的sql數(shù)據(jù)庫。sqlite是由c實現(xiàn)的。廣泛用于包括瀏覽器(支持html5的大部分瀏覽器,ie除外)、ios、android以及一些便攜需求的小型web應(yīng)用系統(tǒng)
    2016-03-03
  • iOS 沙盒圖片保存讀取實例

    iOS 沙盒圖片保存讀取實例

    下面小編就為大家分享一篇iOS 沙盒圖片保存讀取實例,具有很的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • iOS簡單易用的GCD計時器的實現(xiàn)原理

    iOS簡單易用的GCD計時器的實現(xiàn)原理

    在日常開發(fā)中總會碰到需要計時器的功能,常見的定時器有NSTimer、GCD、CADisplayLink。網(wǎng)上也有很多的教程介紹三者的區(qū)別,今天主要講的是GCD這種方式使用以及封裝。感興趣的小伙伴們可以參考一下
    2018-11-11
  • iOS通過shell腳本批量修改屬性

    iOS通過shell腳本批量修改屬性

    這篇文章主要給大家分享了iOS通過shell腳本批量修改屬性的相關(guān)知識點,希望我們整理的內(nèi)容能夠幫助到大家。
    2018-03-03
  • iOS開發(fā)tips-UINavigationBar的切換效果

    iOS開發(fā)tips-UINavigationBar的切換效果

    這篇文章主要為大家詳細介紹了iOS開發(fā)tips-UINavigationBar的切換效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • iOS開發(fā)之表視圖詳解

    iOS開發(fā)之表視圖詳解

    表視圖是iOS開發(fā)中最重要的視圖,它以列表的形式展示數(shù)據(jù)。本篇文章詳細的介紹了表視圖的幾種用法,有需要的小伙伴可以了解一下。
    2016-11-11
  • 淺談SwiftUI 里面$0是什么意思如何用

    淺談SwiftUI 里面$0是什么意思如何用

    這篇文章主要介紹了淺談SwiftUI 里面$0是什么意思如何用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • iOS手勢密碼的實現(xiàn)方法

    iOS手勢密碼的實現(xiàn)方法

    這篇文章主要為大家詳細介紹了iOS手勢密碼的實現(xiàn)方法,教會大家如何實現(xiàn)手勢密碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Swift 2.1 為 UIView 添加點擊事件和點擊效果

    Swift 2.1 為 UIView 添加點擊事件和點擊效果

    本文主要介紹 Swift UIView,這里給大家提供代碼示例作為參考為UIView 添加點擊事件和點擊效果,希望能幫助IOS開發(fā)的同學(xué)
    2016-07-07
  • iOS使用AVFoundation展示視頻

    iOS使用AVFoundation展示視頻

    這篇文章主要為大家詳細介紹了iOS使用AVFoundation展示視頻,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04

最新評論