首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何阻止代码等待连接

如何阻止代码等待连接
EN

Stack Overflow用户
提问于 2015-04-11 00:12:07
回答 3查看 139关注 0票数 2

我一直在为一些sensorTag编写一个新的api。我需要等待连接解决,否则我的代码将在第一次运行失败。我有以下代码片段:

代码语言:javascript
复制
- (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电话。但是我觉得等待一个固定的时间是不好的,最好是在连接的时候继续。但是当我使用When循环时,我的应用程序就会停止工作。不要撞车,停下来。有人能告诉我为什么会这样吗。既然我已经验证了连接只需要2秒的时间,那么我没有发现执行while循环有什么问题吗?另外,是否有更好的方法“等待”东西完成/变得干燥。

提前感谢

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-04-11 17:33:19

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

  1. 如果要循环等待状态更改,可以将其分派到后台线程(如卢克神秘地建议的那样)。这可以防止应用程序阻塞主线程。 问题是,在一个持续轮询的过程中,仍然有一个线程被捆绑在一起,以查看isDeviceConnected是否为真。这相当于一个坐在汽车后座上的孩子不停地问:“我们到了吗?”
  2. 更好的是,您可以采用事件驱动模式,例如使用Matteo建议的KVO。这样,您将在isDeviceConnected属性更改时得到通知,而不是不断轮询此代码。 如果不提供完成块,但确实异步地更改了某些属性,这是一种更有效的方法,而且是一种很好的方法。
  3. 最好的情况是,因为MSBSensorUV是您自己的类,所以可以重构它以提供连接完整的处理程序块。这样,您就可以避免上述方法带来的复杂情况。

脱机时,您共享了一些MSBSensorUV实现:

代码语言:javascript
复制
+ (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前缀可以清楚地表明您在处理单个实例):

代码语言:javascript
复制
+ (instancetype)sharedSensor {
    static MSBSensorUV *uvObject;
    static dispatch_once_t once_token;
    dispatch_once(&once_token, ^{
        uvObject = [[MSBSensorUV alloc] init];
    });
    return uvObject;
}

其次,init不应该启动连接。

代码语言:javascript
复制
- (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;
}

坦率地说,在单例的上下文中,如果没有附加的带,返回nil的概念可能没有意义(因为一旦将其设置为nil,在终止应用程序之前,就再也无法访问该单例)。因此,您可能也希望从init中提取这种逻辑,但我将让您自己来处理。

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

代码语言:javascript
复制
@property (nonatomic, copy) void (^connectionCompletionHandler)(BOOL success, NSError *);

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

代码语言:javascript
复制
- (void)connectWithCompletionHandler:(void (^)(BOOL success, NSError *error))block
{
    self.connectionCompletionHandler = block;
    
    [[MSBClientManager sharedManager] connectClient:self.client];
}

然后,连接委托方法将调用此完成处理程序,例如clientDidConnect将调用:

代码语言:javascript
复制
if (self.connectionCompletionHandler) {
    self.connectionCompletionHandler(TRUE, nil);
    self.connectionCompletionHandler = nil;
}

didFailToConnectWithError会报告失败:

代码语言:javascript
复制
if (self.connectionCompletionHandler) {
    self.connectionCompletionHandler(FALSE, error);
    self.connectionCompletionHandler = nil;
}

最后,回到原来的代码示例,看起来如下:

代码语言:javascript
复制
- (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);
        }
    }];
}
票数 2
EN

Stack Overflow用户

发布于 2015-04-11 00:17:00

您可以使用KVO来观察变量:

self.sensorGyro.client.isDeviceConnected

变量更改时,观察者将收到通知。

因此,您应该首先显示一个旋转器(加载),并设置:

self.view.userInteractionEnabled = NO;

然后,当您收到通知时,应该删除旋转器,并将用户交互设置为已启用(是)。

添加一个观察者很容易:

代码语言:javascript
复制
[self.sensorGyro.client addObserver:self forKeyPath:@"isDeviceConnected" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

必须添加此方法,当变量更改时将调用该方法:

代码语言:javascript
复制
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"isDeviceConnected"]) {
        // Your code here
    }
}

最后,请记住删除方法-dealloc中的观察者

代码语言:javascript
复制
- (void)dealloc
{
    [self.self.sensorGyro.client removeObserver:self ....];
}

重要的是:如果属性isDeviceConnected 是使用访问器方法设置的,通知就会自动发送,因此: self.isDeviceConnected**.**。

欲知更多信息,我建议您阅读关于KVO的苹果文档

票数 1
EN

Stack Overflow用户

发布于 2015-04-11 00:37:26

我建议使用dispatch_async命令。

本质上,您将在代码中添加一个级别的多线程功能。我可能错了,但我会重写您的代码,类似于这样:

代码语言:javascript
复制
- (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");

    dispatch_async(dispatch_get_main_queue(), ^{
         [self.sensorGyro.client.sensorManager startGyroUpdatesToQueue:nil errorRef:nil withHandler:^(MSBSensorGyroData *GyroData, NSError *error) {
         NSLog(@"Starting updates");
         self.currentGyroLabel.text = [NSString stringWithFormat:@"%lu", GyroData.GyroIndexLevel];
    });
}];
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29572544

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档