1

ios noob here: I have an ipad app as an In/Out board posted in the office. Basically, it runs one app; a TableView of 14 people and whether they are in or out of the office. At their desks, people hit a button on a web page to indicate their status when they leave for lunch, meeting or whatever. The ipad app then contacts our webserver every 5 minutes to retrieve an updated status list.

I've found a couple old postings on Stack, one here, which says all downloading must happen in the foreground of the application. The post is from 2011 so wondering if things have changed? I would rather not have the UI locked-up every 5 minutes if someone wants too look at the bottom of the list while a refresh is happening.

4

3 に答える 3

3

その投稿はアプリがバックグラウンドにあることに関するもので、ユースケースは誰かがアプリを使用していることを示唆しており、それはフォアグラウンドにあります。もちろん、UI スレッドをロックせずにバックグラウンド スレッドで Web リクエストを実行できます。シナリオの一般的なパターンは、ビューが表示されるかアプリがアクティブになったときに、(バックグラウンド スレッドで) データを更新し、(メイン スレッドで) テーブルを更新してから、タイマーを自動更新用に設定します (そして無効にします)。アプリがバックグラウンドに入るとき)、ある種の「プルして更新」機能を実装する可能性があります ( 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以前のものであるか、私の理解レベルには複雑すぎます。さらに他の例は、もはや開発中ではないサードパーティのライブラリに依存していました。より最新のさらに別の例では、30 秒のタイムアウトがあり、すべてを完了する必要があります (ios7 fetch)。これは、ビジー状態の 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 に答える