iOS新手,最近做一个物流相关的项目,tableView展示,cell中有一个“距离”标签需要计算后展示(百度地图SDK计算后代理回调结果),数据没有办法第一时间获得。
image.png
目前想到有两个方法解决以上问题:
1.得到model数组 -> 获取当前位置 -> 调用百度地图路算方法 -> 每个model得到结果 -> talbeView reloadData
2.得到model数组┬> tableView reloadData └> 获取当前位置 -> 调用地图路算方法 -> 每个model得到结果 -> 跟新cell对应label
明显,方法1的耗时会比方法2长,影响用户体验。方法2的思路关键在于,得到回调结果后发送通知,让cell更改label,上代码
Request.m
- (void)addDistanceWithModelData:(id)data myLocation:(CLLocationCoordinate2D)coordinate {
//创建队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
//data 有两种 根据类型 转换,可以不用理解
NSArray *array = [data isKindOfClass:[TJMOrderData class]] ? ((TJMOrderData *)data).content : ((TJMMyOrderData *)data).data;
//遍历得到的数组(中有model),逐个请求获得路程
[array enumerateObjectsUsingBlock:^(TJMOrderModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
CLLocationCoordinate2D endCoordinate = CLLocationCoordinate2DMake(obj.consignerLat.doubleValue, obj.consignerLng.doubleValue);
//骑行距离计算,直接从百度地图copy来的
[[TJMLocationService sharedLocationService] calculateRidingDistanceWithDelegate:obj startPoint:coordinate endPoint:endCoordinate];
}];
});
}
Model.m
//代理方法回调 <BMKRouteSearchDelegate>
#pragma mark 返回驾乘搜索结果
- (void)onGetRidingRouteResult:(BMKRouteSearch *)searcher result:(BMKRidingRouteResult *)result errorCode:(BMKSearchErrorCode)error {
if (error == BMK_SEARCH_NO_ERROR) {
BMKRidingRouteLine *plan = (BMKRidingRouteLine *)[result.routes firstObject];
// 计算路线方案中的路段数目
self.getDistance = @(plan.distance / 1000.0);
//发送通知,通知的名字就是model的内存地址(唯一性);
NSString *notiKey = [NSString stringWithFormat:@"%p",self];
[[NSNotificationCenter defaultCenter] postNotificationName:notiKey object:nil userInfo:@{@"model":self}];
}
}
Cell.m
- (void)setViewWithModel:(TJMOrderModel *)model {
if (!model) return;
self.currentModel
//根据model状态 设置 按钮 title
/*
//...省略设置其他view的代码
*/
//我到取货点位置
//先置为零
self.myToGetDistanceLabel.text = @"约0.0KM";
if (model.getDistance) {
//如果有就更新label
self.myToGetDistanceLabel.text = [NSString stringWithFormat:@"约%.2fKM",[model.getDistance doubleValue]];
} else {
//如果没有,就添加通知
NSString *notiKey = [NSString stringWithFormat:@"%p",_currentModel];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modelDistanceDidGet:) name:notiKey object:nil];
}
//种类 尺寸
self.typeNameLabel.text = model.item.itemName;
self.remarkLabel.text = [NSString stringWithFormat:@"%@kg",model.objectWeight];
}
#pragma mark - 通知
- (void)modelDistanceDidGet:(NSNotification *)notification {
TJMOrderModel *model = notification.userInfo[@"model"];
if ([model isEqual:self.currentModel]) {
self.myToGetDistanceLabel.text = [NSString stringWithFormat:@"约%.2fKM",[model.getDistance doubleValue]];
//移除通知
NSString *notiKey = [NSString stringWithFormat:@"%p",model];
[[NSNotificationCenter defaultCenter] removeObserver:self name:notiKey object:nil];
}
}
距离结果的回调在主线程中,cell中的代码 对 model.getDistance 判断, 如果不为空,则直接赋值,不添加通知,如果为空,则说明回调还没调用,添加通知,等待回调后,发送通知,接收通知后更改结果,并删除通知!所以并不会造成多余的通知!(但是在本文编写过程中想到,这样其实是违反MVC原则的,MVC框架 View 和 Model 不能直接通讯,感觉目前项目到更好的改进办法,希望大神指点)
第一次写文章,虽然可能并不实用,但也算是提供了一种思路吧。