我正在编写一个iOS应用程序,用于扫描参与零售点的条形码,在客户扫描收据上印有的QR码后,该位置将代表客户捐赠给慈善机构。
我想向用户发送本地通知,如果他们在参与的位置60秒或更长时间,提醒他们扫描他们可能从他们在那里购买的收据。
我的问题是,当用户进入某个区域时,我想延迟60秒的通话 - 如果在这60秒后他们仍然在该区域发出本地通知 - 但是,有时会在stillInRegion内调用sendLocalNotification在应用程序返回前台之前不会触发。我相信这与线程有时会在延迟结束之前结束,但我不确定。我已经尝试过在stackoverflow和其他地方(块,nstimers等)可以找到的每种方法,但无济于事。关于如何更好地解决这个问题的任何想法?
- (void) sendLocalNotification:(NSString *)regionId {
NSLog(@"we entered %@ and we're currently in %@", regionId, self.currentRegionId);
if ([regionId isEqualToString:self.currentRegionId]) {// if we're still in the region, send a local notification
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil) return;
NSDate *fireTime = [[NSDate date] addTimeInterval:2]; // adds 2 secs
localNotif.fireDate = fireTime;
localNotif.alertBody = [NSString stringWithFormat:@"Did you just visit %@? If so, don't forget to scan your receipt!", regionId];
localNotif.applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber+1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
}
}
- (void) stillInRegion:(CLRegion *)region {
NSLog(@"did enter region: %@", region.identifier);
[self performSelector:@selector(sendLocalNotification:) withObject:region.identifier afterDelay:60];
}
- (void) locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
if (self.didLaunchForRegionUpdate) {
NSString *path = [DGGeofencingHelper applicationDocumentsDirectory];
NSString *finalPath = [path stringByAppendingPathComponent:@"notifications.dg"];
NSMutableArray *updates = [NSMutableArray arrayWithContentsOfFile:finalPath];
if (!updates) {
updates = [NSMutableArray array];
}
NSMutableDictionary *update = [NSMutableDictionary dictionary];
[update setObject:region.identifier forKey:@"fid"];
[update setObject:[NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]] forKey:@"timestamp"];
[update setObject:@"enter" forKey:@"status"];
[updates addObject:update];
[updates writeToFile:finalPath atomically:YES];
} else {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"enter" forKey:@"status"];
[dict setObject:region.identifier forKey:@"fid"];
NSString *jsStatement = [NSString stringWithFormat:@"DGGeofencing.regionMonitorUpdate(%@);", [dict JSONString]];
[self.webView stringByEvaluatingJavaScriptFromString:jsStatement];
}
self.currentRegionId = region.identifier;
self.cRegionEnterTime =[NSDate date];
[self stillInRegion:region];
}
答案 0 :(得分:1)
是否在前台调用了locationManager:didEnterRegion,然后你的应用程序转到后台? 我不太清楚你何时调用这些方法,但你可以尝试按如下方式创建后台任务:
致电[self stillInRegion:region]之前;添加以下代码:
bgTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^ {}];
它应该调用你的stillInRegion方法,即使你去后台也继续,所以延迟应该继续指望!最后,您应该结束后台任务。为此,请在send块之后的sendLocalNotification方法的末尾添加以下行:
[[UIApplication sharedApplication] endBackgroundTask:bgTaskIdentifier];
如果有帮助,请告诉我们!对不起,我的英语很差!
祝你有个美好的一天!
答案 1 :(得分:1)
在我的didEnterRegion方法中,我曾经使用以下代码来实现所需的结果:
UIApplication* app = [UIApplication sharedApplication];
bgTaskIdentifier = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTaskIdentifier];
bgTaskIdentifier = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSTimer* t = [NSTimer scheduledTimerWithTimeInterval:180 target:self selector:@selector(stillInRegion:) userInfo:region.identifier repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:t forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
非常接近@ lucaslt89的内容,但略有不同。