我一直在为一些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电话。但是我觉得等待一个固定的时间是不好的,最好是在连接的时候继续。但是当我使用When循环时,我的应用程序就会停止工作。不要撞车,停下来。有人能告诉我为什么会这样吗。既然我已经验证了连接只需要2秒的时间,那么我没有发现执行while循环有什么问题吗?另外,是否有更好的方法“等待”东西完成/变得干燥。
提前感谢
发布于 2015-04-11 17:33:19
MSBSensorUV类正在启动一些异步连接进程。
isDeviceConnected是否为真。这相当于一个坐在汽车后座上的孩子不停地问:“我们到了吗?”isDeviceConnected属性更改时得到通知,而不是不断轮询此代码。
如果不提供完成块,但确实异步地更改了某些属性,这是一种更有效的方法,而且是一种很好的方法。MSBSensorUV是您自己的类,所以可以重构它以提供连接完整的处理程序块。这样,您就可以避免上述方法带来的复杂情况。脱机时,您共享了一些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;
}坦率地说,在单例的上下文中,如果没有附加的带,返回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];
}然后,连接委托方法将调用此完成处理程序,例如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);
}
}];
}发布于 2015-04-11 00:17:00
您可以使用KVO来观察变量:
self.sensorGyro.client.isDeviceConnected
当变量更改时,观察者将收到通知。
因此,您应该首先显示一个旋转器(加载),并设置:
self.view.userInteractionEnabled = NO;
然后,当您收到通知时,应该删除旋转器,并将用户交互设置为已启用(是)。
添加一个观察者很容易:
[self.sensorGyro.client addObserver:self forKeyPath:@"isDeviceConnected" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];必须添加此方法,当变量更改时将调用该方法:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"isDeviceConnected"]) {
// Your code here
}
}最后,请记住删除方法-dealloc中的观察者
- (void)dealloc
{
[self.self.sensorGyro.client removeObserver:self ....];
}重要的是:如果属性isDeviceConnected 是使用访问器方法设置的,通知就会自动发送,因此: self.isDeviceConnected**.**。
欲知更多信息,我建议您阅读关于KVO的苹果文档。
发布于 2015-04-11 00:37:26
我建议使用dispatch_async命令。
本质上,您将在代码中添加一个级别的多线程功能。我可能错了,但我会重写您的代码,类似于这样:
- (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];
});
}];https://stackoverflow.com/questions/29572544
复制相似问题