1

ios noob here:我有一个 ipad 应用程序作为输入/输出板张贴在办公室。基本上,它运行一个应用程序;包含 14 人的 TableView,以及他们是否在办公室。在他们的办公桌上,人们在离开去吃午饭、开会或其他什么时候点击网页上的一个按钮来显示他们的状态。然后 ipad 应用程序每 5 分钟联系我们的网络服务器以检索更新的状态列表。

我在 Stack 上找到了几篇旧帖子,其中一篇在这里,其中说所有下载都必须在应用程序的前台进行。这篇文章是 2011 年的,所以想知道事情是否发生了变化?如果有人想在刷新时查看列表底部,我宁愿不要每 5 分钟锁定一次 UI。

4

3 回答 3

3

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

如果你做这些事情,当人们查看应用程序时,你的数据将是最新的,用户可以通过拉动刷新来保证它。

于 2013-09-18T18:40:17.187 回答
1

是的!事情变了。现在可以(从 iOS 7 开始)在应用程序处于后台时运行 HTTP 请求。

为此,您需要将该值添加fetch到应用的UIBackgroundModesInfo.plist 键中。

有关更多详细信息,请参阅iOS 应用程序编程指南

于 2013-09-18T18:29:15.197 回答
0

在查看了大量代码和令人眼花缭乱的方法之后,我真的找不到一个“简单”的例子。网上的很多例子都是 ARC 之前的,或者对我的理解水平来说太复杂了。还有其他示例取决于不再开发的 3rd 方库。还有一些最新的例子有 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);
}
于 2013-09-19T19:32:39.827 回答