unity3d 当Unity应用程序处于后台时,如何在iOS中收集指南针数据?

yk9xbfzb  于 2023-03-23  发布在  iOS
关注(0)|答案(1)|浏览(205)

我对Objective-C和Swift知之甚少,但在花了几个小时编写了一个本地插件,使用iOS中的后台线程收集指南针数据后,下面是到目前为止的插件

// MyPlugin.m
 
extern "C" {
#import <CoreLocation/CoreLocation.h>
#import "MyPlugin.h"
 
@implementation MyPlugin
 
NSThread *_magneticHeadThread;
BOOL _shouldStop;
NSMutableArray *readings;
 
- (void)startBackgroundThread {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        // Put your code here that should run in the background when the app enters background.
        NSLog(@"Background thread started!");
        readings = [NSMutableArray array];
        _magneticHeadThread = [[NSThread alloc] initWithTarget:self selector:@selector(retrieveMagneticHeadPosition) object:nil];
        [_magneticHeadThread start];
    });
}
 
- (void)applicationDidEnterBackground:(NSNotification *)notification {
    _shouldStop = NO;
    [self startBackgroundThread];
}
 
- (void)applicationWillEnterForeground:(NSNotification *)notification {
    _shouldStop = YES;
    [_magneticHeadThread cancel];
    NSLog(@"Magnetic head position: %lu", [readings count]);
}
 
+ (instancetype)sharedInstance {
    static MyPlugin *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyPlugin alloc] init];
    });
    return sharedInstance;
}
 
- (void)retrieveMagneticHeadPosition {
    CLLocationManager *locationManager = [[CLLocationManager alloc] init];
   
    locationManager.headingFilter = kCLHeadingFilterNone;
    [locationManager startUpdatingHeading];
    int c = 0;
    while (!_shouldStop) {
       
        NSLog(@"Magnetic head position: %i", c);
        c++;
        [readings addObject:@(locationManager.heading.magneticHeading)];
        [NSThread sleepForTimeInterval:0.1];
    }
   
    [locationManager stopUpdatingHeading];
}
 
@end
 
 
void UnityMyPlugin_StartBackgroundThread() {
    [[NSNotificationCenter defaultCenter] addObserver:[MyPlugin sharedInstance] selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
   
    [[NSNotificationCenter defaultCenter] addObserver:[MyPlugin sharedInstance] selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
}

它在Start函数的MonoBehaviour中被调用:

void Start()
    {
        Application.runInBackground = true;
#if UNITY_IPHONE && !UNITY_EDITOR
        UnityMyPlugin_StartBackgroundThread();
#endif
    }

我已经读到dispatch_async期望在固定时间内完成,但我没有找到任何关于无限线程的线索,也没有关于服务的信息来请求信息,如magneticHeading,你能告诉我在哪里检查或向谁询问解决方案吗?我在寻找任何可能的东西吗?我在这段代码中做了什么不好的选择吗?谢谢
这个解决方案,它的编译和工作~ 2s之前被取消的SO,但我正在寻找一个线程,收集数据的一个较长的时间或服务,要求一系列的时间戳,并获得信息。

yc0p9oo0

yc0p9oo01#

你在这里的方法是错误的。你没有在线程上不断地轮询CLLocationManager。你启动一次CLLocationManager,让它运行你想要的信息。应用程序将定期接收更新。不需要任何类型的线程,也绝对不需要轮询循环。
有关获取权限和其他所需设置,请参阅Configuring your app to use location services。有关在后台阅读位置信息的更多详细信息,请参阅Handling location updates in the background。您的应用不会在后台持续轮询信息。操作系统将在事件可用时交付事件,并可能在需要时启动您的应用。
虽然当前的问题不需要线程或队列,但值得注意的是,DISPATCH_QUEUE_PRIORITY_BACKGROUND是一个非常低优先级的队列,当应用程序处于后台时,它通常根本不会运行。(我从未真正想过这个名字有多反直觉。)即使在应用程序处于后台时应该运行此代码的情况下,您也不希望使用该优先级。
一般来说,如果你发现自己在使用sleepForTimeInterval:,你可能做错了什么,它有时候是正确的工具,但是非常罕见,特别是如果你是一个初学者。

相关问题