【问题标题】:Running code in the background in IOSIOS后台运行代码
【发布时间】:2013-07-14 20:09:00
【问题描述】:
Firebase * ref = nil;


NSInteger iid = [[API sharedInstance] userid];
NSString * path = [NSString stringWithFormat:  @"http://example.firebaseIO.com/user/%d/conversations", iid];

ref = [[Firebase alloc] initWithUrl:path];


if(ref) {

    NSString * path = [NSString stringWithFormat: @"http://example.firebaseIO.com/conversations"];
    Firebase * conv = [[Firebase alloc] initWithUrl: path];

    [ref observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {

        // name of conversation
        NSString * name = snapshot.name;
        Firebase * ref1 = [conv childByAppendingPath: name];

        [ref1 observeSingleEventOfType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {

            if(snapshot.value != [NSNull null] && ![snapshot.value isKindOfClass: [NSString class]])
            {
                FDataSnapshot * chatsnapshot = [snapshot childSnapshotForPath: @"chats"];

                NSInteger numChatMessages = chatsnapshot.childrenCount;
                numberOfTotalChatMessages += numChatMessages;

                NSMutableDictionary *m = [snapshot.value mutableCopy];
                [m setValue: snapshot.name forKey: @"ref_name"];

                NSInteger current_user = [[API sharedInstance] userid];
                NSString * userpath = [NSString stringWithFormat: @"users/%d", current_user];
                FDataSnapshot * usersnapshot = [snapshot childSnapshotForPath: userpath];

                if(usersnapshot.value != [NSNull null] && ![usersnapshot.value isKindOfClass: [NSString class]])
                {
                    NSDictionary * userdict = usersnapshot.value;
                    NSInteger numUserMessagesRead = [userdict[@"numOfMessages"] intValue];

                    numberOfMessagesRead += numUserMessagesRead;

                    if(numberOfTotalChatMessages > numberOfMessagesRead) {
                        [m setValue: @"true" forKey: @"bubble"];
                    }
                }

                [self.chats addObject: m];

                NSNumber * index = [NSNumber numberWithInt: self.chats.count - 1];
                [read setValue: index forKey: snapshot.name];

                PLRightMenuViewController * rightPanel = (PLRightMenuViewController *) self.viewController.rightPanel;
                [rightPanel.tableView reloadData];

                self.numChats = numberOfTotalChatMessages - numberOfMessagesRead;
                [[UIApplication sharedApplication] setApplicationIconBadgeNumber: self.numChats];

            }
        }];

    }];


    [ref observeEventType:FEventTypeChildChanged withBlock:^(FDataSnapshot *snapshot) {

        NSString * name = snapshot.name;
        Firebase * ref1 = [conv childByAppendingPath: name];

        [ref1 observeSingleEventOfType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot)
        {
            if(snapshot.value != [NSNull null] && ![snapshot.value isKindOfClass: [NSString class]])
            {
                numberOfTotalChatMessages += 1;

                NSMutableDictionary *m = [snapshot.value mutableCopy];
                [m setValue: snapshot.name forKey: @"ref_name"];
                [m setValue: @"true" forKey: @"bubble"];
                [self.chats addObject: m];


                if([read objectForKey: snapshot.name])
                {
                    NSInteger index = [[read objectForKey: snapshot.name] intValue];
                    [self.chats removeObjectAtIndex: index];

                     NSNumber * index1 = [NSNumber numberWithInt: self.chats.count - 1];
                    [read setValue: index1 forKey: snapshot.name];
                }

                self.numChats = numberOfTotalChatMessages - numberOfMessagesRead;
                [[UIApplication sharedApplication] setApplicationIconBadgeNumber: self.numChats];


                PLRightMenuViewController * rightPanel = (PLRightMenuViewController *) self.viewController.rightPanel;
                [rightPanel.tableView reloadData];
            }
        }];

    }];
}

我有上面的代码,它基本上使用 firebase 检查任何新的聊天对话并更改应用程序徽章编号。如何在应用程序后台运行代码,以便无论是否有人当前使用该应用程序,都可以更改应用程序徽章编号?

基本上,我怎样才能在后台运行上面的代码?我应该在 Appdelegate 中进行哪些更改?

【问题讨论】:

标签: ios objective-c ios4 firebase


【解决方案1】:

除非你作弊,否则你不能。目前 iOS 或 Apple 分别不允许应用程序进入后台,只有极少数例外。例如定位服务或播放音频。

有些人通过假装播放某种声音来作弊。

到目前为止,您必须使用推送通知来通知应用收到的消息并更新徽章。

或者……等待 iOS 7 发布。假设您有一个开发者帐户,您已经可以访问文档和预览/测试版资源并做好准备,直到 iOS 7 和 SDK 等成为 GA。

【讨论】:

    【解决方案2】:
    // @interface
    
    // Declare Private property
    @property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
    
    //@end
    // ...
    
    // Copy into
    //@implementation 
    
    - (void)setupBackgrounding {
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(appBackgrounding:)
                                                     name: UIApplicationDidEnterBackgroundNotification
                                                   object: nil];
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(appForegrounding:)
                                                     name: UIApplicationWillEnterForegroundNotification
                                                   object: nil];
    }
    
    - (void)appBackgrounding: (NSNotification *)notification {
        [self keepAlive];
    }
    
    - (void) keepAlive {
        self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
            self.backgroundTask = UIBackgroundTaskInvalid;
            [self keepAlive];
        }];
    }
    
    - (void)appForegrounding: (NSNotification *)notification {
        if (self.backgroundTask != UIBackgroundTaskInvalid) {
            [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
            self.backgroundTask = UIBackgroundTaskInvalid;
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用这些方法,将后台任务运行更多时间..

      - (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler  NS_AVAILABLE_IOS(4_0);
      - (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier NS_AVAILABLE_IOS(4_0);
      
      - (BOOL)setKeepAliveTimeout:(NSTimeInterval)timeout handler:(void(^)(void))keepAliveHandler NS_AVAILABLE_IOS(4_0);
      - (void)clearKeepAliveTimeout NS_AVAILABLE_IOS(4_0);
      
      
      
      - (void)getDataFromServer
      
          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      
              [self beginBackgroundUpdateTask];
      
              NSURLResponse * response = nil;
              NSError  * error = nil;
              NSData * responseData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
      
              // Do something with the result
      
              [self endBackgroundUpdateTask];
          });
      }
      - (void) beginBackgroundUpdateTask
      {
          self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
              [self endBackgroundUpdateTask];
          }];
      }
      
      - (void) endBackgroundUpdateTask
      {
          [[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];
          self.backgroundUpdateTask = UIBackgroundTaskInvalid;
      }
      

      如果你想让你的应用程序保持活力,你可以使用这个:-

      - (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,
          // called instead of applicationWillTerminate: when the user quits.
      
          if ([application respondsToSelector:@selector(setKeepAliveTimeout:handler:)]) 
          {
              [application setKeepAliveTimeout:600 handler:^{
      
                  DDLogVerbose(@"KeepAliveHandler");
      
                  // Do other keep alive stuff here.
              }];
          }
      }
      

      它可能会帮助你.. 在 iOS 7 中可能有更好的方法来做到这一点......

      【讨论】:

        【解决方案4】:

        您需要使用Apple Push Notification服务,通常缩写为APN。

        【讨论】:

          【解决方案5】:

          您可以使用推送通知来做到这一点,这是一个很好的解释。
          example http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1
          注意:您需要一个 APNS 来通知您的应用程序。
          在 iOS7 中,带有 fetchAPI 的功能允许您在后台工作,但请注意,您的应用程序不会在后台运行,因为系统将决定何时允许应用程序在后台运行。
          在 iOS7 中还有另外一件事叫做静默推送通知,它可以让你在通知到来时更新你的视图,这意味着如果你的应用程序在后台并且通知来了,你可以在后台更改应用程序徽章编号。

          【讨论】:

            猜你喜欢
            • 2013-06-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-07-24
            • 2014-02-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多