如何在ios中运行后台HTTP进程?

时间:2013-09-18 18:21:26

标签: ios objective-c process

ios noob:我在办公室张贴了一个ipad应用程序作为In / Out板。基本上,它运行一个应用程序;一个14人的TableView,无论他们是在办公室还是在办公室外。在他们的办公桌上,人们点击网页上的按钮,以便在他们出去吃午餐,开会或其他什么时表明他们的状态。然后ipad应用程序每隔5分钟联系我们的网络服务器以检索更新的状态列表。

我在Stack上发现了一些旧帖子,一个here,表示所有下载必须发生在应用程序的前台。该帖子是2011年,所以想知道事情是否发生了变化?如果有人想要在刷新过程中看到列表的底部,我宁愿不要每5分钟锁定一次用户界面。

3 个答案:

答案 0 :(得分:3)

该帖子是关于应用程序在后台,您的用例表明有人正在使用该应用程序,它位于前台。您当然可以在后台线程上执行Web请求而无需锁定UI线程。您的方案的一般模式是,当视图出现或应用程序变为活动状态时,刷新数据(在后台线程上),刷新表(在主线程上),然后设置计时器以进行自动刷新(并禁用当应用程序进入后台时,它可能实现某种“拉动刷新”功能(https://github.com/enormego/EGOTableViewPullRefresh)。

如果您执行这些操作,那么当用户查看应用时,您的数据将是最新的,用户可以通过拉动刷新来保证数据。

答案 1 :(得分:1)

是的!事情变了。现在可以(从iOS 7开始)在应用程序背景下运行HTTP请求。

要执行此操作,您需要将值fetch添加到应用的UIBackgroundModes Info.plist键。

有关详细信息,请参阅iOS App Programming Guide

答案 2 :(得分:0)

在查看了大量代码和令人眼花缭乱的方法之后,我真的找不到一个“简单”的例子。网上的许多例子都是预先ARC,或者对我的理解水平来说过于复杂。还有其他例子取决于不再开发的第三方库。还有其他更新的例子,有30秒的超时,其中一切都必须完成(ios7提取),这似乎不足以在繁忙的Wi-Fi网络上快速下载。最后,我确实设法将一个工作样本拼凑在一起,每隔20秒运行一次后台下载。不知道如何更新UI。

AppDelegate.m

#import "bgtask.h"
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  bgtask *b = [[bgtask alloc] initTaskWithURL:@"http://www.google.com" app:application];
  return YES;
}

bgtask.h

#import <Foundation/Foundation.h>

@interface bgtask : NSOperation
@property (strong, atomic) NSMutableData *webData;
@property (strong, atomic) UIApplication *myApplication;
- (id) initTaskWithURL:(NSString *)url  app:(UIApplication *)application;
@end

bgtask.m

#import "bgtask.h"
@implementation bgtask
UIBackgroundTaskIdentifier backgroundTask;
@synthesize webData = _webData;
@synthesize myApplication = _myApplication;
NSString *mURL;

// connect to webserver and send values. return response data
- (void) webConnect
{  
   NSURL *myURL = [NSURL URLWithString:mURL];
   _webData = [NSData dataWithContentsOfURL:myURL];

   if (_webData)
   {
      // save response data if connected ok
      NSLog(@"connetion ok got %ul bytes", [_webData length]);  
   }
   else
   {
      NSLog(@"connection failed");
      //TODO: some error handling
   }
}

- (void) timerTask:(NSTimer *) timer
{
   backgroundTask = [_myApplication beginBackgroundTaskWithExpirationHandler:
   ^{
      dispatch_async(dispatch_get_main_queue(),
      ^{
         if (backgroundTask != UIBackgroundTaskInvalid)
         {
            [_myApplication endBackgroundTask:backgroundTask];
            backgroundTask = UIBackgroundTaskInvalid;
         }
      });
   }];

   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
   ^{
      NSLog (@"Running refresh...");
      [self webConnect];

      dispatch_async(dispatch_get_main_queue(),
      ^{
         if (backgroundTask != UIBackgroundTaskInvalid)
         {
            [_myApplication endBackgroundTask:backgroundTask];
            backgroundTask = UIBackgroundTaskInvalid;
         }
      });
   });

}

- (id) initTaskWithURL:(NSString *)url  app:(UIApplication *)application
{
   self = [super init];
   if (self)
   {
      // setup repeating refresh task. 
      // Save url, application for later use
      mURL = [[NSString alloc] initWithString:url];
      _myApplication = application;
      [NSTimer scheduledTimerWithTimeInterval:20.0
                                       target:self
                                     selector:@selector(timerTask:)
                                     userInfo:nil
                                      repeats:YES];
      NSLog (@"task init");
    }// if self

    return (self);
}