我工作的iOS应用程序有一个苹果手表应用程序随之而来。我们最近开始抱怨GPS距离更新速度减慢,手表落后于手机几秒钟。我一直在研究这个并写了一些测试代码,来自[[WCSession defaultSession] sendMessage:message
replyHandler:replyHandler
errorHandler:errorHandler
在watchOS 2.2和2.1中的速度肯定是两倍。我已在下面附上测试代码。
#pragma mark - Location Update.
/**
* @description Provides an NSBlockOperation to be executed in an operation queue. This is an attempt to force serial
* processing
*/
- (NSBlockOperation*)distanceUpdateBlock {
NSBlockOperation *blockOp = [[NSBlockOperation alloc] init];
__weak NSBlockOperation * weakOp = blockOp;
__weak typeof(self) weakSelf = self;
[blockOp addExecutionBlock:^{
typeof(weakSelf) blockSafeSelf = weakSelf;
typeof(weakOp) blockSafeOp = weakOp;
if (!blockSafeOp.isCancelled) { // Make sure we haven't already been cancelled.
__block NSDate *startDate = [NSDate date];
__block BOOL completed = NO;
void (^replyBlock)(NSDictionary*) = ^(NSDictionary *message){
if (!blockSafeOp.isCancelled) {
[blockSafeSelf processUserLocationOnWatch:message];
double replyTime = [[NSDate date] timeIntervalSinceDate:startDate];
NSLog(@"Reply Time: %.03f", replyTime);
completed = YES;
}
};
void (^failBlock)(NSError*) = ^(NSError *error) {
if (!blockSafeOp.isCancelled) {
double replyTime = [[NSDate date] timeIntervalSinceDate:startDate];
NSLog(@"Reply Time Fail: %.03f", replyTime);
completed = YES;
}
};
[self fetchUserLocationFromIphoneWithReplyHandler:replyBlock errorHandler:failBlock];
do {
usleep(10000); // 1/100th second wait to throttle evaluations (Don't worry - in final code I will subclass NSOperation and control when it actually finishes - this is for easy testing.)
} while (!completed && !blockSafeOp.isCancelled && [blockSafeSelf isWatchReachable]); //(isWatchReachable just makes sure we have a session with the phone and it is reachable).
}
}];
blockOp.completionBlock = ^{
typeof(weakSelf) blockSafeSelf = weakSelf;
typeof(weakOp) blockSafeOp = weakOp;
if (!blockSafeOp.isCancelled) {
[blockSafeSelf addOperationForLocationUpdate]; // since we are finished - add another operation.
}
};
return blockOp;
}
- (void)addOperationForLocationUpdate {
[distanceUpdateOperationQueue addOperation:[self distanceUpdateBlock]];
}
- (void)startUpdatingLocation {
[self addOperationForLocationUpdate];
}
- (void)stopUpdatingLocation {
[distanceUpdateOperationQueue cancelAllOperations];
}
- (void)fetchUserLocationFromIphoneWithReplyHandler:(nullable void (^)(NSDictionary<NSString *, id> *replyMessage))replyHandler errorHandler:(nullable void (^)(NSError *error))errorHandler {
if (self.isSessionActive) {
NSDictionary *message = @{kWatchSessionMessageTag:kWatchSessionMessageUserLocation};
if (self.isWatchReachable) {
[[WCSession defaultSession] sendMessage:message
replyHandler:replyHandler
errorHandler:errorHandler
];
} else {
errorHandler(nil);
}
} else {
[self activateSession];
errorHandler(nil);
}
}
iPhone端的处理程序只是获取用户位置,并使用编码信息调用replyHandler。
2.2上的时间日志看起来像(一直是一秒钟)
回复时间:0.919
回复时间:0.952
回复时间:0.991
回复时间:0.981
回复时间:0.963
2.1上的相同代码看起来像
回复时间:0.424
回复时间:0.421
回复时间:0.433
回复时间:0.419
另外,我注意到在5分钟(300秒)之后,错误处理程序开始调用已经调用了回复处理程序的消息。我看到有人提到这个问题的另一个帖子,其他人是否有这种情况发生并知道原因?
所以,Q1 - 有没有人遇到这种性能变慢,并想出如何保持replyHandler运行得更快,或者找到更快的方式来获取更新?
Q2 - 5分钟后调用errorHandler的解决方案。
要消除的一些事情 - 我已经完成了在接收消息和调用replyHandler之间测试iOS代码的尽职调查。 iOS 9.2 / 9.3之间的处理时间没有变化。我把它缩小到了这个电话。实际上,我们在以前版本中执行此操作的方式现在正在备份sendMessage的operationQueue。所以现在我用这个测试代码一次强制一个。我们不再备份了,但个别电话很慢。
答案 0 :(得分:0)
所以,我今天在相同的代码上运行测试,使用相同的设备,尽管代码没有改变,但它现在的运行速度是最初的两倍(在2.1中)。日志的范围为.12 - .2秒。从那以后发生的事情只是软件更新。此外,5分钟后不再调用失败块。因此,这个问题的两个部分都神奇地起作用。我目前正在使用iOS 9.3.4(13G35),手表是2.2.2。似乎是处理手表和手机之间队列的链条中某处的操作系统问题。一切都很好。