gpt4 book ai didi

ios - 如何阻止代码等待连接

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:41:02 30 4
gpt4 key购买 nike

我一直在为一些 sensorTag 寻找新的 API。我需要等待连接稳定,否则我的代码片段将在第一次运行时失败。我有以下代码片段:

- (void)viewDidLoad {
[super viewDidLoad];

self.sensorGyro = [MSBSensorUV createObjectGyro];
if(self.sensorGyro){
while (!self.sensorGyro.client.isDeviceConnected) {
NSLog(@"Awaiting connection");
}//Check that connection has been made

NSLog(@"connection UP");

[self.sensorGyro.client.sensorManager startGyroUpdatesToQueue:nil errorRef:nil withHandler:^(MSBSensorGyroData *GyroData, NSError *error) {
NSLog(@"Starting updates");
self.currentGyroLabel.text = [NSString stringWithFormat:@"%lu", GyroData.GyroIndexLevel];
}];

最初我没有 while 循环。我使用了 2-3 秒的 dispatch_after 调用。但是我觉得等一个固定的时间不好,最好是连接上再进行。但是当我使用 while 循环时,我的应用程序就会停止运行。没有崩溃,只是停止。谁能告诉我为什么会这样。因为我已经验证连接只需要 2 秒,所以我没有看到 while 循环有问题?此外,是否有更好的方法来“等待”东西完成/变干。

提前致谢

最佳答案

MSBSensorUV 类正在启动一些异步连接过程。

  1. 如果您要循环等待状态更改,您可以将其分派(dispatch)到后台线程(正如 Luke 隐晦地建议的那样)。这可以防止应用程序阻塞主线程。

    问题是您仍然有一个线程在不断轮询以查看 isDeviceConnected 是否为真。这相当于一个坐在汽车后座上的 child 不断地问“我们到了吗?”

  2. 更好的是,您可以采用事件驱动模式,例如使用 Matteo 建议的 KVO。通过这种方式,您将在 isDeviceConnected 属性更改时收到通知,而不是此代码不断轮询。

    如果您遇到一个不提供完成 block 但会异步更改某些属性的类,这会更有效并且是一种很好的方法。

  3. 最好,因为 MSBSensorUV 是您自己的类,您可以重构它以提供连接完成处理程序 block 。这样,您就可以避免上述方法带来的并发症。


离线时,您分享了一些MSBSensorUV 实现:

+ (MSBSensorUV *)createObjectUV{
static MSBSensorUV *UVObject;
static dispatch_once_t once_token;
dispatch_once(&once_token, ^{
UVObject = [[MSBSensorUV alloc]init];
});
return UVObject;
}

- (MSBSensorUV *)init{
self = [super init];
if(self){
[MSBClientManager sharedManager].delegate = self;
NSArray *clients = [[MSBClientManager sharedManager] attachedClients];
self.client = [clients firstObject];
if(self.client == nil){
//no bands attached
return nil;
}
[[MSBClientManager sharedManager] connectClient:self.client];
}
return self;
}

首先,createObjectUV 正在创建一个单例,因此您应该将其重命名为类似 sharedSensor 的名称(使用 shared 的前缀可以清楚地表明你正在处理一个单例):

+ (instancetype)sharedSensor {
static MSBSensorUV *uvObject;
static dispatch_once_t once_token;
dispatch_once(&once_token, ^{
uvObject = [[MSBSensorUV alloc] init];
});
return uvObject;
}

其次,init 不应启动连接。

- (instancetype)init {
self = [super init];
if (self) {
[MSBClientManager sharedManager].delegate = self;
NSArray *clients = [[MSBClientManager sharedManager] attachedClients];
self.client = [clients firstObject];
if(self.client == nil){
//no bands attached
return nil;
}
// [[MSBClientManager sharedManager] connectClient:self.client];
}
return self;
}

坦率地说,在单例的上下文中,如果没有附加 band 则返回 nil 的想法可能没有意义(因为一旦你将它设置为 nil,你永远不能再访问这个单例,直到你终止应用程序)。因此,您可能也想从 init 中提取该逻辑,但我会让您自己解决这个问题。

第三,您将为连接完成处理程序声明一个属性:

@property (nonatomic, copy) void (^connectionCompletionHandler)(BOOL success, NSError *);

第四,您将创建一个connectionWithCompletionHandler 方法,例如:

- (void)connectWithCompletionHandler:(void (^)(BOOL success, NSError *error))block
{
self.connectionCompletionHandler = block;

[[MSBClientManager sharedManager] connectClient:self.client];
}

然后您的连接委托(delegate)方法将调用此完成处理程序,例如clientDidConnect 会调用:

if (self.connectionCompletionHandler) {
self.connectionCompletionHandler(TRUE, nil);
self.connectionCompletionHandler = nil;
}

didFailToConnectWithError 会报告失败:

if (self.connectionCompletionHandler) {
self.connectionCompletionHandler(FALSE, error);
self.connectionCompletionHandler = nil;
}

最后,回到您的原始代码示例,它看起来像:

- (void)viewDidLoad {
[super viewDidLoad];

self.sensorGyro = [MSBSensorUV sharedSensor];
[self.sensorGyro connectWithCompletionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"connection UP");
[self.sensorGyro.client.sensorManager startGyroUpdatesToQueue:nil errorRef:nil withHandler:^(MSBSensorGyroData *GyroData, NSError *error) {
NSLog(@"Starting updates");
self.currentGyroLabel.text = [NSString stringWithFormat:@"%lu", GyroData.GyroIndexLevel];
}];
} else {
NSLog(@"Error connecting: %@", error);
}
}];
}

关于ios - 如何阻止代码等待连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29572544/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com