此项目演示了如何仅使用设备上存储的数据,就获取 iOS 或 Mac OS X 设备的粗略近似位置。该过程不涉及 GPS 或互联网查找。结果数据仅约为准确,但可能足以确定设备所在的国家或大陆。
方法是对本地时区名称进行查找,然后将其与来自 IANA(http://www.iana.org/time-zones)的数据关联起来。每个区域都提供了一个国家代码和经纬度对。截至本文发表时,全球有数百个时区,因此结果数据可以识别用户的近似地区,而不透露其确切位置。
例如,在美国落基山脉地区,时区名称为 America/Denver
。使用 IANA 的数据给出国家代码 US
和表示为 +394421-1045903
的经纬度对。经纬度信息会转换为 CLLocation
,而国家代码将保留为 NSString
。
这通过在 NSZimeZone
上实现类别来实现,该类别添加了两个方法
- (CLLocation *)abtz_location;
- (NSString *)abtz_countryCode;
这对于 Mac OS X 和 iOS 设备都适用。一般的原理适用于任何使用 IANA 时区数据的计算系统,这在很常见。
一个可能的用例:您的应用程序为一个在多个国家拥有支持电话号码的国家设计。您希望有一个“联系我们”按钮,以便启动电话通话,并希望自动选择与用户所在国家相同的电话号码。但在那之后,您从未使用过位置数据。如果您开始使用 Core Location,您的用户可能会合理地怀疑您为什么突然想要知道他们的位置。但您实际上并不关心他们的位置,至少不是确切的位置。一个粗略的近似绰绰有余。
项目中包含一个演示应用程序,该应用程序显示您的当前时区在地图视图中的位置。如果您点击“显示实际位置”按钮,应用程序将使用 Core Location 获取您的实际位置并显示两个位置。应用程序将不会在您按下此按钮之前请求使用您的位置权限。
该代码包含两个来自IANA的文件。
zone.tab
文件,其中包含了国家和地区代码以及纬度和经度信息。该文件已经在iOS和Mac OS X中存在,路径为/usr/share/zoneinfo/zone.tab
,但为了完整性,该文件也包含在项目中。backward
文件,将旧的时区名称映射到当前名称。这是因为有些旧的名称仍在被广泛使用,例如使用US/Pacific
而不是America/Los_Angeles
,而zone.tab
只包含当前名称。与zone.tab
不同,这个文件通常不在iOS或Mac OS X上存在。这两个文件以原始格式包含在内,以便随时替换为新版本。格式和名称都远非理想,但更新应该非常简单。
扫描这些文件是一个相当昂贵的操作,并且并未进行优化。然而,每次时区实例都会通过Objective-C附加对象缓存其国家代码和位置。如果你只使用代码进行本地时区的处理,缓存查找文件的就不会非常有用。另一方面,如果你预计要查找许多不同的时区数据,一些优化将会是一个非常好的主意。
MIT风格许可协议,详情请见LICENSE。
由Tom Harrington创作,大多数社交网络上的@atomicbird。