您好我正在尝试在后台运行FireBase。
我有以下代码: 代码执行以下操作 - 当应用程序进入后台时,它会不断检查Firebase是否有新的聊天消息。然后,如果找到新的聊天消息,它会递增应用程序徽章编号。
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self.locationManager startMonitoringSignificantLocationChanges];
NSLog(@"in background fetching8");
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) { //Check if our iOS version supports multitasking I.E iOS 4
if ([[UIDevice currentDevice] isMultitaskingSupported]) { //Check if device supports mulitasking
UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance
__block UIBackgroundTaskIdentifier background_task; //Create a task object
background_task = [application beginBackgroundTaskWithExpirationHandler: ^ {
[application endBackgroundTask: background_task]; //Tell the system that we are done with the tasks
background_task = UIBackgroundTaskInvalid; //Set the task to be invalid
//System will be shutting down the app at any point in time now
}];
//Background tasks require you to use asyncrous tasks
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Perform your tasks that your application requires
NSLog(@"in background fetching98");
inBackGround = YES;
[self fetch];
[application endBackgroundTask: background_task]; //End the task so the system knows that you are done with what you need to perform
background_task = UIBackgroundTaskInvalid; //Invalidate the background_task
});
}
}
// 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.
}
取:
- (void) fetch
{
if([[API sharedInstance] isAuthorized])
{
NSLog(@"in background fetching");
Firebase * ref = nil;
NSDictionary * investor = [[API sharedInstance] investor];
NSDictionary * startup = [[API sharedInstance] startup];
if(investor != nil) {
NSInteger iid = [[API sharedInstance] userid];
NSString * path = [NSString stringWithFormat: @"http://example.firebaseIO.com/investor/%d/conversations", iid];
ref = [[Firebase alloc] initWithUrl:path];
}
else if(startup != nil)
{
NSInteger sid = [[startup objectForKey: @"id"] intValue];
NSString * path = [NSString stringWithFormat: @"http://example.firebaseIO.com/startup/%d/conversations", sid];
ref = [[Firebase alloc] initWithUrl:path];
}
if(ref)
{
NSString * path = [NSString stringWithFormat: @"http://kickcircle.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]])
{
NSLog(@"in background fetching7");
FDataSnapshot * chatsnapshot = [snapshot childSnapshotForPath: @"chats"];
NSInteger numChatMessages = chatsnapshot.childrenCount;
numberOfTotalChatMessages += numChatMessages;
NSMutableDictionary *m = [snapshot.value mutableCopy];
[m setValue: snapshot.name forKey: @"ref_name"];
// number of messages read for that conversation
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];
if(numChatMessages > numUserMessagesRead)
{
if([[m objectForKey: @"last_from_id"] intValue] != [[API sharedInstance] userid])
{
[m setValue: @"true" forKey: @"bubble"];
newChats = YES;
if(inBackGround)
{
[self addNotification];
}
}
else{
numUserMessagesRead = numChatMessages;
}
}
else {
numUserMessagesRead = numChatMessages;
}
numberOfMessagesRead += numUserMessagesRead;
[m setValue: [NSNumber numberWithInt: numUserMessagesRead] forKey: @"numMessagesRead"];
}
else {
if([[m objectForKey: @"last_from_id"] intValue] != [[API sharedInstance] userid])
{
[m setValue: @"true" forKey: @"bubble"];
newChats = YES;
[m setValue: [NSNumber numberWithInt: 0] forKey: @"numMessagesRead"];
if(inBackGround)
{
[self addNotification];
}
}
else {
numberOfMessagesRead += numChatMessages;
[m setValue: [NSNumber numberWithInt: numChatMessages] forKey: @"numMessagesRead"];
}
}
[m setValue: [NSNumber numberWithInt: numChatMessages] forKey: @"numChatMessages"];
[self.chats addObject: m];
[self calculateChatNumber];
NSNumber * index = [NSNumber numberWithInt: self.chats.count - 1];
[read setValue: index forKey: snapshot.name];
PLRightMenuViewController * rightPanel = (PLRightMenuViewController *) self.viewController.rightPanel;
[rightPanel.tableView reloadData];
}
}];
}];
[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]])
{
NSLog(@"in background fetching8");
NSMutableDictionary *m = [snapshot.value mutableCopy];
[m setValue: snapshot.name forKey: @"ref_name"];
numberOfTotalChatMessages += 1;
if([read objectForKey: snapshot.name])
{
NSInteger index = [[read objectForKey: snapshot.name] intValue];
// number of current chats for conversation
NSInteger numChats = [[[self.chats objectAtIndex: index] objectForKey: @"numChatMessages"] intValue];
// number of messages read
NSNumber * readMessages = [[self.chats objectAtIndex: index] objectForKey: @"numMessagesRead"];
NSInteger readMessagesInt = [readMessages intValue];
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];
if([[m objectForKey: @"last_from_id"] intValue] != [[API sharedInstance] userid]) {
newChats = YES;
[m setValue: @"true" forKey: @"bubble"];
if(numUserMessagesRead > readMessagesInt) {
numberOfMessagesRead += numUserMessagesRead - readMessagesInt;
readMessagesInt = numUserMessagesRead;
if(inBackGround)
{
[self addNotification];
}
}
}
else {
numberOfMessagesRead += numChats + 1 - readMessagesInt;
readMessagesInt = numChats + 1;
}
}
else {
if([[m objectForKey: @"last_from_id"] intValue] != [[API sharedInstance] userid])
{
[m setValue: @"true" forKey: @"bubble"];
newChats = YES;
if(inBackGround)
{
[self addNotification];
}
}
else {
numberOfMessagesRead += numChats + 1 - readMessagesInt;
readMessagesInt = numChats + 1;
}
}
[self.chats removeObjectAtIndex: index];
[m setValue: [NSNumber numberWithInt: numChats + 1] forKey: @"numChatMessages"];
[m setValue: [NSNumber numberWithInt: readMessagesInt] forKey: @"numMessagesRead"];
[self.chats addObject: m];
NSNumber * index1 = [NSNumber numberWithInt: self.chats.count - 1];
[read setValue: index1 forKey: snapshot.name];
}
[self calculateChatNumber];
PLRightMenuViewController * rightPanel = (PLRightMenuViewController *) self.viewController.rightPanel;
[rightPanel.tableView reloadData];
}
}];
}];
}
}
}
由于某些原因,当应用程序进入后台时,它无效(当有新消息时徽章不会递增)。我做错了什么?
答案 0 :(得分:2)
您尝试在后台运行的方法保留用于后台任务完成 - 实际上它不适用于代码的操作执行。您应该转到推送通知模型,或等待iOS 7合并更新。
beginBackgroundTaskWithExpirationHandler:在应用程序被暂停之前,即使应用程序被移动到后台状态,您的应用也希望完成任务的iOS。 endBackgroundTask:表示您的应用程序任务已完成的iOS,允许它在需要时将您的应用程序移动到暂停状态。如果应用程序一直保持在前台,那么这些调用无效,因此使用它们并没有什么坏处。
请注意,后台任务无法自由统治,也无法无限期地完成任务。 beginBackgroundTaskWithExpirationHandler:的“expiration handler”部分是一个块,用于指定清理代码,如果任务超出其生命周期。作为后台任务执行的代码不得进行任何UI更新或openGL调用(因为应用程序在屏幕外)。
我认为你最多可以达到10分钟。