我创建了一个基于ibeacons和location的小应用程序。
我正在调用一个Web服务来下载一些信息。
当我从didFinishLaunchingWithOptions调用函数“downloadDataFromServerWithMajor”时,它的工作正常。
当应用程序在后台并且“startMonitoringSignificantLocationChanges”调用“didUpdateLocations”回调时出现问题。来自Manager.m的“fetchNetworkFromMajor”正在触发,我得到两个日志:
NSLog(@"fetchNetworkFromMajor -->PATH:%@", path);
NSLog(@"fetchNetworkFromMajor -->major:%@ -->version:%ld -->language:%@", major, (long)version, language);
但从那以后没有任何事情发生,没有响应对象或get函数的错误。
[self GET:path parameters:nil
success:^(NSURLSessionDataTask *task, id responseObject) {
NSMutableArray *networks = [[NSMutableArray alloc] initWithCapacity:[responseObject count]];
NSLog(@"responseObject: %@", responseObject );
Network *net = [[Network alloc] initWithJSONDictionary:responseObject];
if (net) {
NSLog(@"NET:%@", net);
[networks addObject:net];
}
successHandler(networks);
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"error manager:%@", error);
errorHandler(error);
}];
我的代码(来自AppDelegate.m和Manager.m)如下:
AppDelegate.m
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self downloadDataFromServerWithMajor:@"1" andVersion:1];
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
id locationValue = [launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey];
[self.locationManager startMonitoringSignificantLocationChanges];
NSString *message =[NSString stringWithFormat:@"UIApplicationLaunchOptionsLocationKey %@",locationValue];
[self sendLocalNotificationWithMessage:message];
}
if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
NSLog(@"RESPONDS!!!!!");
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeSound|UIUserNotificationTypeBadge categories:nil]];
}
// Override point for customization after application launch.
NSUUID *beaconUUID = [[NSUUID alloc] initWithUUIDString:@"B9407F30-F5F8-466E-AFF9-25556B57FE6A"];
NSString *regionIdentifier = @"iBeacons region 1";
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID: beaconUUID identifier: regionIdentifier ];
beaconRegion.notifyEntryStateOnDisplay = YES;
self.locationManager = [[CLLocationManager alloc]init];
if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){
[self.locationManager requestAlwaysAuthorization];
}
self.locationManager.delegate = self;
[self.locationManager startMonitoringForRegion:beaconRegion];
return YES;
}
- (void) locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region{
if(beacons.count > 0){
for (CLBeacon *beacon in beacons){
NSLog(@"beacon detectado major: %@ minor: %@", beacon.major,beacon.minor);
}
}
}
- (void) locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
[manager startRangingBeaconsInRegion:(CLBeaconRegion*) region];
NSLog(@"didEnterRegion --> has entrado en la region");
}
- (void) locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{
[manager stopRangingBeaconsInRegion:(CLBeaconRegion*) region];
NSLog(@"didExitRegion --> has salido de la region");
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{
if (state == CLRegionStateInside) {
//Start Ranging
[manager startRangingBeaconsInRegion:(CLBeaconRegion*) region];
NSLog(@"didDetermineState -->has entrado en la region");
}else{
//Stop Ranging
[manager stopRangingBeaconsInRegion:(CLBeaconRegion*) region];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
//[self detectBluetooth];
NSString *message = @"didUpdateLocations";
[self sendLocalNotificationWithMessage:message];
[self downloadDataFromServerWithMajor:@"1" andVersion:1];
}
-(void)sendLocalNotificationWithMessage:(NSString*)message {
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = message;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSString *message =@"applicationDidEnterBackground";
[self sendLocalNotificationWithMessage:message];
[self.locationManager startMonitoringSignificantLocationChanges];
// 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) downloadDataFromServerWithMajor: (NSString *) major andVersion: (NSInteger) version
{
//downloadDataFromServer
NSString * language = [[NSLocale preferredLanguages] objectAtIndex:0];
NSLog(@"downloadDataFromServerWithMajor -->major: %@ -->version:%ld", major,(long)version);
[[MyFacade sharedInstance] fetchNetworkFromMajor: major andVersion: version andLanguage: language withDelegate:self errorHandler:self];
}
-(void)didEndFetchingNetwork:(NSArray *)network{
NSLog(@"didEndFetchingNetwork");
}
-(void)networkFetchingEror:(NSError *)error
{
NSLog(@"error networkFetchingEror");
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSString *message =@"applicationDidBecomeActive";
[self sendLocalNotificationWithMessage:message];
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
Manager.m
-(void)fetchNetworkFromMajor:(NSString *)major andVersion:(NSInteger )version andLanguage: (NSString *) language
successHandler:(void (^)(NSArray *pois))successHandler
errorHandler:(void (^)(NSError *error))errorHandler {
NSString *path = [NSString stringWithFormat:ManagerFetchNetworkRelativeURLFormat,
major,(long)version, language];
NSLog(@"fetchNetworkFromMajor -->PATH:%@", path);
NSLog(@"fetchNetworkFromMajor -->major:%@ -->version:%ld -->language:%@", major, (long)version, language);
[self GET:path parameters:nil
success:^(NSURLSessionDataTask *task, id responseObject) {
NSMutableArray *networks = [[NSMutableArray alloc] initWithCapacity:[responseObject count]];
NSLog(@"responseObject: %@", responseObject );
Network *net = [[Network alloc] initWithJSONDictionary:responseObject];
if (net) {
NSLog(@"NET:%@", net);
[networks addObject:net];
}
successHandler(networks);
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"error manager:%@", error);
errorHandler(error);
}];
}
我不明白为什么从“didFinishLaunchingWithOptions”运行时同一个调用正常工作,并且从“didUpdateLocations”运行时没有任何反应。 有任何想法吗?我真的很沮丧这个问题。
添加Manager的初始化
+ (instancetype)sharedInstance
{
static MyManager *_sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// Network activity indicator manager setup
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
// Session configuration setup
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.HTTPAdditionalHeaders = @{
@"User-Agent" : @"iOS Client"
};
NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:10 * 1024 * 1024 // 10MB. memory cache
diskCapacity:50 * 1024 * 1024 // 50MB. on disk cache
diskPath:nil];
sessionConfiguration.URLCache = cache;
sessionConfiguration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
//sessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;
// Initialize the session
_sharedInstance = [[MyManager alloc] initWithBaseURL:[NSURL URLWithString:MyManagerBaseURL] sessionConfiguration:sessionConfiguration];
});
return _sharedInstance;
}
编辑:我添加了调用[self downloadDataFromServerWithMajor:@“1”andVersion:1];方法didRangeBeacons:当应用程序在背景上删除ibeacon时,调用也可以。
答案 0 :(得分:0)
要在后台下载,必须将NSURLSessionConfiguration初始化为后台会话。
Apple Documentation for background downloads
在Manager初始化中尝试此操作
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"bgDownload"];