注:本篇文章翻译自:https://developers.arcgis.com/ios/objective-c/guide/create-an-offline-map.htm;
你可以为用户提供离线地图,使得他们在网络不好或是不存在的情况下依然可以工作。要创建离线地图,你得创建地理数据库和切片缓存,然后创建图层。这些正是本篇文章所要介绍的。
你可以添加下列特性:
1)可视化底图(也称为平铺层,从切片缓存中创建);
2)编辑操作数据(属性数据和矢量数据)。包括查询和编辑位置、形状、属性、相关表和附属功能。
3)如果你的数据是基于服务的,当再次联机时(上传编辑数据或下拉别人已经编辑过的更新属性),可以实现同步编辑。
4)能够执行位置(地理编码和反编码)和路线的快速查询功能。
离线模式
ArcGIS Runtime offline提供有两种主要模式:
服务模式:最适合支持大量用户的情况,这种模式允许多个离线用户编辑相同数据层,并且当再次联网时可以同步编辑。
桌面模式:最适合具有需要定期更新只读数据的应用程序。
服务模式
最适合支持大量用户的情况,这种模式允许多个离线用户编辑相同数据层,并且当再次联网时可以同步编辑。
对于可操作数据,你可以利用ArcGIS for Server、ArcGIS OnLine、或是ArcGIS门户提供的同步要素服务将数据下载到你的设备中去,以供离线使用。通过同步的过程,你可以控制用户是否可以上传或是它们的变化。同时也使得应用程序可以查看该字段下一阶段的新的数据。当有多个用户编辑相同的要素并且编辑发生了冲突时,那么最后的编辑将同步到服务上,从而覆盖掉其它的编辑。
对于底图数据,ArcGIS 切片地图服务和ArcGIS Online地图允许按需创建切片缓存,让你把你的底图下线。
桌面模式
桌面模式允许用户使用在ArcGIS桌面端创建的ArcGIS Runtime 内容,比较适合于需要定期更新只读数据的App。桌面端模式主要包括要素、表格数据、切片缓存、网络数据集和定位器。
包含操作数据
你可以用两种方法来为离线地图准备操作数据:
1)使用API(服务模式)的同步要素服务创建geodatabase;
2)使用ArcGIS桌面端(桌面模式)创建geodatabase;
在部分主要介绍操作数据的准备并将其添加到你到你的应用程序中去。
从同步要素服务中生成地理数据库(geodatabase)
要为离线应用生成地理数据库(geodatabase),你需要从ArcGIS server 10.2.2或是更高版本或是ArcGIS online提供的要素服务,同时该要素服务必须能够同步。
一旦你拥有了可以同步的要素服务,便可以为你感兴趣的区域创建地理数据库;这为你的要素创建了拷贝,利用它便可以在离线状态下工作了。利用AGSDBSyncTask 类提供的方法可以请求和下载地理数据库。
当创建了供离线使用的地理数据库后,你提供的参数允许你控制以下内容:
1)在地理数据库中的图层;
2)地理数据库的范围;
3)地理数据库的空间参考系;
4)地理数据库是否包括要素附件;
5)地理数据库同步模型;
6)是否在特定的范围只包含要素的子集,通过指定层来查询,以利用属性值来过滤要素。
地理数据库的范围
从ArcGIS 要素服务上请求的地理数据库的范围一般是一个外包(envelope)。然而,它仍支持点、线、面的几何形状,允许更复杂的数据提取被定义。不论几何类型如何,和提供的几何体相交的要素被提取。
同步模型
同步模型控制如何对地理数据进行某一字段的修改,并在同步的过程中反过来应用的要素服务中去。受支持的模型是由用来创建同步要素服务的数据定义的。如果数据没有版本控制,那么同步模式是“每一层”模式,这同时也是最灵活的模式,根据你指定的图层,允许你在一层接一层的基础上进行同步。如果数据受版本控制,那么同步模型是“每一个”模式,它将一次性同步整个地理数据库,包括所有的层和表。
创建地理数据库(geodatabase)
要从你感兴趣区域的同步要素服务中请求地理数据库,须利用AGSGDBSyncTask 类。
下面的代码段向你展示了如何可以做到这一点:
@property (strong,nonatomic) AGSGDBSyncTask *geodatabaseTask;
@property (nonatomic,strong) id<AGSCancellable> geodatabaseJob;
@property (strong, nonatomic) AGSGDBGenerateParameters *generateParameters;
@property (strong) IBOutlet AGSMapView *mapView;
@property (strong) AGSGDBFeatureTable *localFeatureTable;
@property (strong) AGSFeatureTableLayer *localFeatureTableLayer;
...
//Set parameters for the feature extent
//The Ids of the feature layers
//The synchronization model
//The output spatial reference
self.generateParameters = [[AGSGDBGenerateParameters alloc]initWithExtent:anAreaOfInterest layerIDs:@[@0]];
self.generateParameters.syncModel = AGSGDBSyncModelPerLayer;
self.generateParameters.outSpatialReference = self.mapView.spatialReference;
//Create the geodatabase task
self.geodatabaseTask =
[[AGSGDBSyncTask alloc] initWithURL:[NSURL URLWithString:kFeatureServiceURL] credential:nil];
//Use a weak variable for self within the blocks
__weak typeof(self) *weakSelf = self;
//If the geodatabase task loads then proceed to
//generate and download the geodatabase
self.geodatabaseTask.loadCompletion = ^(NSError *error){
if (error) {
NSLog(@"AGSGDBSyncTask failed to load!");
}
else {
//Generate the geodatabase (with parameters)
weakSelf.geodatabaseJob =
[weakSelf.geodatabaseTask
generateGeodatabaseWithParameters:weakSelf.generateParameters
downloadFolderPath:nil
useExisting:NO
//Status block - provides feedback form the asynchronous job
status:^(AGSResumableTaskJobStatus status, NSDictionary *userInfo){
NSLog(@"Status: %@", status);
}
//Completion block - executes when the job has completed.
//This code creates a AGSFeatureTableLayer from the first table in the
//returned geodatabase.
completion:^(AGSGDBGeodatabase *geodatabase, NSError *error){
if (error) {
NSLog(@"Error fetching geodatabase:%@",error);
}
else {
weakSelf.localFeatureTable = [[geodatabase featureTables] objectAtIndex:0];
weakSelf.localFeatureTableLayer = [[AGSFeatureTableLayer alloc] initWithFeatureTable:weakSelf.localFeatureTable];
weakSelf.localFeatureTableLayer.delegate = weakSelf;
[weakSelf.mapView addMapLayer:weakSelf.localFeatureTableLayer withName:@"Offline Feature Layer"];
}
}
]
}
};
你的地理数据库现在应该已经作为geodatabase文件存储在你的电脑上了。
从ArcGIS桌面端创建一个地理数据库
用ArcGIS桌面端10.2.1或者更高的版本的“创建ArcGIS Runtime 内容”方法来创建一个地理数据库。
添加地理数据库的内容到你的app中
1)利用AGSDBGeodatabase的类来打开地理数据库,该类将路径“thePathString”传递给类的构造函数。该类利用其自身方法可以列出地理数据库文件中的功能表和属性。
AGSGDBGeodatabase *gdb = [AGSGDBGeodatabase alloc]initWithPath:thePathString error:(NSError *error);
2)要素层用来展示地图上的要素。要从地理数据库中创建一个要素层,首先要从地理数据库中提取出要素表,然后从要素表中创建一个要素层。地理数据库可能包含几个数据库要素表,这取决于你在地理数据库创建过程中请求的图层。如果地理数据库是从同步要素服务中创建的,那么你可以通过与要素服务层相对应的ID号来获取要素表。
@property (strong,nonatomic) AGSGDBFeatureTable *localFeatureTable;
@property (strong,nonatomic) AGSFeatureTableLayer *localFeatureTableLayer;
localFeatureTable = [[geodatabase featureTables] objectAtIndex:0];
localFeatureTableLayer = [[AGSFeatureTableLayer alloc] initWithFeatureTable:localFeatureTable];
localFeatureTableLayer.delegate = self;
3)将要素层添加到地图中。该图层一旦被添加和初始化,你的要素就会在地图上显示。你将要在地图上看到的要素取决于所显示的地图范围。如果你的要素没有出现,请确保你是否将地图平移或是缩放到一个合适的程度,以及地理数据库的空间参考系与地图的是否匹配。当然你可以在地理数据库生成时设置空间参考系。