原来的应用使用的是后台一直定位正常,升级到xcode9后,无法定位,在隐私定位中看到的应用是永不。在info.Plist中的添加新Key NSLocationAlwaysAndWhenInUseUsageDeion和旧Key NSLocationWhenInUseUsageDeion。仍然没有用,卸载应用后再安装,看到脸定位的永不状态也没有了。
我以前解决了两天天没有搞定这个老工程不能定位的问题,新建的项目在iOS11下可以定位(是直接建立工程,不是拷贝过来一个老工程修改下)。由于换工作,不做曹操专车的软件,新的公司的应用没有使用位置定位功能,由于项目忙,所以就没有进一步的解决。
今天我终于有时间,再次研究老工程无法定位的问题,我感觉是配置项哪里没有生效引起的。更新了高德定位sdk,下载高德定位demo,比较代码发现没有什么区别,demo都是定位回调正常的,但是自己的老工程就是没有定位回调,并且日志打印:
2018-07-31 14:12:01.357574+0800 OutdoorClub[31564:2724613] [AMapLocationKit] 要在iOS 11及以上版本使用定位服务, 需要在Info.plist中添加NSLocationAlwaysAndWhenInUseUsageDescription和NSLocationWhenInUseUsageDescription字段。
原来的高德sdk是不打印这个信息的,所以以前定位更困难,这就距离Ios11发布过去快一年,要是这个问题别的应用没有解决,那么打车软件就不能用了,所以很可能还是配置问题。我又把这个字段加上去,仍旧报这个错。
程序员的精神告诉我;没有跨不过的坎,是没有踩不完的坑。想想我用WKWebView代替UIWebView时踩过几十个坑,当时我甚至怀疑有些功能WKWebView就不能实现,最终我还是迈过去了。但是WKWebView虽然后多好处,但是那么多年UIWebView还是没有完全代替,估计也是和这些大坑有关吧!采用更新的技术总要有流血流汗的准备,阵痛是有的,但是我们最终会越来越接近完美。做程序员重在思路。若做一个错误的功能,你做的再解决需求仍旧做不完美的体验,所以我们也要对不对的需求进行建议性修改。有时候程序猿的思路卡壳了,你就是通宵也不一定能解决了。所以要听听别人的解决方法,特别是做苹果app开发和安卓app开发的技术上是想通的,毕竟苹果系统和安卓也是一家亲,互相抄袭。上次我遇到一个js标签图标图片的iOS app图片替换问题,我想了一周就没有解决了。把百度上的所有的相关文章的方法都试了一遍,结果功能没有实现,结果产生post请求无法发送参数的大问题。看来网上的解决方案是有特定环境和要求的,和我们的需求完全不相同。但是网上的解决方案思路是正确的,只是有些关键的细节有问题,虽然它的demo运行正常,并不能说明它没有问题。本来天下的文章一抄。这个app 定位的问题也是一个典型的一抄走遍天下。解决方案肯定不全面。
以我解决问题的方式,不放过任何细节,怀疑的都要试一试,那么试错了也没有什么,只是浪费一些时间,又没有别人批评你。
1. 怀疑高德的地图key有问题。去干,在高德demo上换掉地图key和bundle identifier,结果高德demo定位正常,地图显示正常。分析高德的地图模块和定位模块是分开的,不会是key的问题。看来我想多了。但是有时后就是这样,你认为不会发生的,可能真的就会发生奇迹,不过这次奇迹没有出现。
2. 怀疑由于我模块化没有把定位开始函数放在AppDelegate.m文件里,仍旧还是没有任何定位信息。
3. 怀疑在info.plist文件里增加NSLocationAlwaysAndWhenInUseUsageDescription和NSLocationWhenInUseUsageDescription字段后需要重新安装应用,结果卸载应用再安装还是依然。
4.
4. 怀疑没有进行授权检查。按照官方文档增加下面的代码:
地图定位单例的部分代码:
- (instancetype)init { self = [super init]; if (self) { self.locationManager = [[AMapLocationManager alloc] init]; #if DEBUG self.locationManager.distanceFilter = kCLLocationAccuracyBestForNavigation; #else self.locationManager.distanceFilter = kCLLocationAccuracyBestForNavigation; #endif self.locationManager.pausesLocationUpdatesAutomatically = NO; self.locationManager.locatingWithReGeocode = NO; if (IOS_VERSION_LARGE_OR_EQUAL(9.0)) { [self.locationManager setAllowsBackgroundLocationUpdates:YES]; } CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; if(kCLAuthorizationStatusNotDetermined == status) { CLLocationManager *locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; if (IOS_VERSION_LARGE_OR_EQUAL(9.0)) { [locationManager requestWhenInUseAuthorization]; } else { [locationManager requestAlwaysAuthorization]; } } self.locationManager.delegate = self; self.searchAPI = [[AMapSearchAPI alloc] init]; self.searchAPI.delegate = self; [self setupCommand]; } return self; }
结果还是没有定位信息。虽然问题不是出在这里,iOS11确实需要这些检查。iOS11把永远定位降低为使用时定位。所以原来的requestAlwaysAuthorization函数要换成requestWhenInUseAuthorization。
5. 怀疑工程Target的Capabilities的Background Modes重的Location Updates没有勾选。查看后也勾选。
6. 在现在使用的其它应用中加入定位的功能,仍旧不能定位。
7. 求助我朋友,它建立的工程定位很正常。总不能把我以前的代码搬移到他的demo里把,那样工程也太浩大了。若是项目紧急,找不到原因真的可能怎么做。有方案总比无方案好。那也是没有办法的临时办法。
8. 怀疑工程里有配置错误。突然发现工程中有一个info配置,点开一看,其中Custom IOS Target Prpperties和Info.plist很像,并发现确实没有NSLocationAlwaysAndWhenInUseUsageDescription和NSLocationWhenInUseUsageDescription字段,只有Privacy - Location Always Usage Description。我赶紧去掉Privacy - Location Always Usage Description,加上Privacy - Location Always and When In Use Usage Description和Privacy - Location When In Use Usage Description。运行果然定位授权信息弹出来了,并且地图定位也正常。
这个问题的解决方案找到可真不容易啊!苹果的官方文章也没有任何说明,这不是坑我们程序猿吗?让我们上蹿下跳吗?网上的文章抄来抄去,不断的误导我们。做程序就是这样失之毫厘谬以千里,一个零可以让你倾家荡产。
缺少配置的配置项:
修改正确的配置项:
弹出定位授权页面和没有获得定位信息时高德显示的地图是北京的地图:
地图收到正确的定位信息的地图定位图:
把截屏的图片或网上下载的图片下载的图片保存到相册,也有类似的问题。就是在info.plist增加了Privacy - Photo Library Additions Usage Description(增加图片到系统相册的权限)属性字段,但是工程的Info配置项中没有对应的字段,导致app保存图片到相册时崩溃的问题,并非每个工程都遇到,但是部分老工程有可能遇到,至少我的app因此而崩溃了。