iOS ArcGIS 10.2.5 詳細(xì)介紹

經(jīng)常有人問我戳杀,ArcGIS怎么弄其馏,怎么弄。

作為當(dāng)年在廈門搞過商業(yè)級天地圖項目的我來說少态,是時候展現(xiàn)一波技術(shù)了惰聂,就把干貨告訴大家疆偿,讓大家好好搞。不僅會介紹API搓幌,還會介紹思路杆故,以及分析過程等等。

前公司項目:天地圖·廈門溉愁,已發(fā)布在App Store处铛,歡迎下載查看。

天地圖·廈門 首頁

[AGSRuntimeEnvironment setClientID:clientID error:&error];

用來設(shè)置認(rèn)證拐揭,只有通過認(rèn)證撤蟆,地圖才不會顯示開發(fā)版。

self.mapView.locationDisplay.showsPing = NO;//取消閃爍的光圈

self.mapView.locationDisplay.showsAccuracy = NO;//取消閃爍的光圈

通過這兩段代碼可以取消ArcGIS閃爍的光圈堂污。

self.mapView.locationDisplay.location.accuracy = 10;

設(shè)置定位精度家肯,單位是米。

self.mapView.layerDelegate = self;

設(shè)置層代理盟猖,主要用到了mapViewDidLoad的代理方法讨衣,當(dāng)?shù)貓D加載完成時調(diào)用。

self.mapView.touchDelegate = self;

設(shè)置觸碰代理式镐,主要用到了didClickAtPoint的代理方法值依,當(dāng)點擊地圖時調(diào)用。

self.mapView.minScale = 100000000;

self.mapView.maxScale = 1000;

設(shè)置地圖的放大倍數(shù)和縮小倍數(shù)碟案,ArcGIS不會自己縮小到很小愿险,需要你來設(shè)置,通過設(shè)置這個參數(shù),可以看到門牌號辆亏。

[self.mapView enableWrapAround];

設(shè)置允許地圖環(huán)繞风秤,如果不設(shè)置這個參數(shù),左右滑動地圖時會到底扮叨。比如向左滑動到美國時就停止了缤弦,設(shè)置了這個參數(shù),滑動到美國彻磁,可以繼續(xù)左滑到英國碍沐,再回到美國,形成循環(huán)衷蜓。

AGSSpatialReference *sr = [AGSSpatialReference spatialReferenceWithWKID:4490];

AGSEnvelope *env = [AGSEnvelope envelopeWithXmin:117.85362348365

ymin:24.398242072050003

xmax:118.48276347535

ymax:24.93150561495

spatialReference:sr];

[self.mapView zoomToEnvelope:env animated:NO];

設(shè)置初始定位區(qū)域累提,我將它定位在廈門。

以上方法我放在viewDidLoad方法中執(zhí)行磁浇。

[self.mapView.locationDisplay startDataSource];

在地圖上顯示設(shè)備位置斋陪。

[self.mapView.locationDisplay addObserver:self

forKeyPath:@"autoPanMode"

options:(NSKeyValueObservingOptionNew)

context:NULL];

監(jiān)聽地圖的定位情況,用來控制當(dāng)前是否處于地圖的中心

[self.mapView addObserver:self

forKeyPath:@"mapScale"

options:(NSKeyValueObservingOptionNew)

context:NULL];

地圖縮放系數(shù)改變時調(diào)用置吓,我用來取消搜索框鍵盤无虚。

[self.mapView addObserver:self

forKeyPath:@"visibleAreaEnvelope"

options:(NSKeyValueObservingOptionNew)

context:NULL];

地圖可見區(qū)域監(jiān)測,實時獲取地圖中心位置衍锚,糾錯的時候可以用到友题。

[[NSNotificationCenter defaultCenter] addObserver:self

selector:@selector(mapViewDidEndZooming:)

name:AGSMapViewDidEndZoomingNotification

object:nil];

地圖停止縮放時觸發(fā),用來判斷是否需要移除全球地圖戴质,提高加載速度咆爽。

[[NSNotificationCenter defaultCenter] addObserver:self

selector:@selector(mapViewDidEndPanning:)

name:AGSMapViewDidEndPanningNotification

object:nil];

地圖停止平移時觸發(fā)。

UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self

action:@selector(handleMapPan:)];

[self.mapView addGestureRecognizer:panGestureRecognizer];

處理地圖平移置森。

以上方法我放在mapViewDidLoad方法中執(zhí)行。

[self.mapView zoomIn:YES];

[self.mapView zoomOut:YES];

地圖的放大和縮小操作符糊。

TDTTiledServiceLayer *tianDiTuLyr = [[TDTTiledServiceLayer alloc] initWithLayerType:type LocalServiceURL:nil error:&err];

添加全球地圖操作凫海,TDTTiledServiceLayer是我自己自定義的類,用來加載全球地圖用的男娄。遺憾的是行贪,ArcGIS并沒有使用一個類來處理加載這一類型全球底圖的操作,所以要自己去實現(xiàn)模闲,而這個實現(xiàn)過程過于復(fù)雜建瘫,我當(dāng)初也是花了不少時間,篇幅的限制尸折,就不在這里細(xì)細(xì)展開啰脚,因為細(xì)細(xì)展開的話,文章太長太長了实夹。

[self.mapView insertMapLayer:tianDiTuLyr withName:name atIndex:0];

在某個層級插入地圖橄浓。地圖上放置一張底圖粒梦,如果上面有什么信息的話荸实,就往上面加一層,需要什么樣的信息准给,就疊加什么樣的層,層級處理的理論基礎(chǔ)與iOS視圖或者cocos 2D都是一樣的露氮。

id tiledLayer = [AGSLocalTiledLayer localTiledLayerWithPath:fileName];

加載本地圖層祖灰,如果本地有tpk文件,可以直接加載夫植。tpk文件和離線地圖有緊密的關(guān)系油讯,因為離線地圖下載下來的就是tpk文件详民,tpk文件是離線地圖數(shù)據(jù)格式,之后會說到離線地圖陌兑。

id tiledLayer = [MDTiledMapServiceLayer tiledMapServiceLayerWithURL:url];

MDTiledMapServiceLayer是我自己定義的沈跨,繼承于AGSTiledMapServiceLayer兔综,根據(jù)需要,可能要重寫urlForTileKey方法软驰,并配置好column、row纠吴、level等信息慧瘤,而level信息要與服務(wù)端約定好。

以上內(nèi)容是圖層的初始化和疊加操作锅减。

接下來介紹專題圖的加載。

所謂的專題圖握联,無非是各種功能或者數(shù)據(jù)顯示圖,比如在地圖上顯示自行車位置拴疤,顯示水壩位置,顯示公園位置呐矾,這些都是一個個圖層蜒犯,需要往地圖上疊加组橄。而加載這些圖層用到的地圖類也不盡相同罚随。比如:

AGSDynamicMapServiceLayer layer = [AGSDynamicMapServiceLayer dynamicMapServiceLayerWithURL:url];

用來加載動態(tài)圖層淘菩。

AGSGraphicsLayer *graphicsLayer = [AGSGraphicsLayer graphicsLayer];

用來加載圖像層遵班。

我目前用到這兩個,當(dāng)然還有其他很多圖層潮改,之前都有研究過狭郑,走過不少彎路。

AGSCredential *credential = [[AGSCredential alloc] initWithToken:data.appToken referer:data.appReferer];

地圖憑證汇在,保證系統(tǒng)的安全和對用戶的控制。

AGSQueryTask *queryTask = [AGSQueryTask queryTaskWithURL:url credential:credential];

queryTask.delegate = self;

創(chuàng)建查詢?nèi)蝿?wù)亩鬼。

AGSQuery *query = [AGSQuery query];

query.whereClause = data.whereClause;

query.outFields = [NSArray arrayWithObject:@"*"];

query.returnGeometry = YES;

query.outSpatialReference = self.mapView.spatialReference;

[queryTask executeWithQuery:query];

創(chuàng)建查詢參數(shù)阿蝶。

查詢?nèi)蝿?wù)和查詢參數(shù)用于顯示圖層上已經(jīng)標(biāo)出的指定的點。有些需求可能需要對這些點進(jìn)行抽稀玷过,我在抽稀過程中使用了冒泡算法焚廊,加了點動態(tài)規(guī)劃习劫。

AGSIdentifyTask *identifyTask = [AGSIdentifyTask identifyTaskWithURL:url];

identifyTask.delegate = self;

創(chuàng)建一個Id任務(wù),之前使用這個去加載袒餐,因為內(nèi)容定制度較差,后來改用服務(wù)端進(jìn)行灸眼。

但無論是查詢?nèi)蝿?wù)或者Id任務(wù),它們都需要設(shè)置代理霉囚,然后實現(xiàn)代理的方法匕积,確保操作得到響應(yīng)。

接下來介紹測距和測面盅粪。

AGSSketchGraphicsLayer *measureSketchLayer = [AGSSketchGraphicsLayer graphicsLayer];

需要使用到該圖層悄蕾,在這圖層上進(jìn)行繪制。

然后你需要理解圖層上幾個相關(guān)變量的含義帆调,比如:

midVertexSymbol

allowHitTest

vertexSymbol

selectedVertexSymbol

mainSymbol

geometry

特別是geometry贷帮,幾種幾何圖形不同的創(chuàng)建方式如下:

//創(chuàng)建線

measureSketchLayer.geometry = [[AGSMutablePolyline alloc] initWithSpatialReference:self.mapView.spatialReference];

//創(chuàng)建面

measureSketchLayer.geometry = [[AGSMutablePolygon alloc] initWithSpatialReference:self.mapView.spatialReference];

記得設(shè)置一下地圖的觸摸代理。

self.mapView.touchDelegate = measureSketchLayer;

下面的通知撵枢,AGSSketchGraphicsLayerGeometryDidChangeNotification锄禽,是用來監(jiān)測幾何體的形狀變化。

[[NSNotificationCenter defaultCenter] addObserver:self

selector:@selector(respondToGeomChanged:)

name:AGSSketchGraphicsLayerGeometryDidChangeNotification

object:nil];

在這個方法里面處理距離變化或者面積變化沃但,以及處理之后要介紹的標(biāo)繪內(nèi)容。

介紹一下距離和面積的計算方法:

AGSGeometry *sketchGeometry = measureSketchLayer.geometry;

AGSGeometryEngine *geometryEngine = [AGSGeometryEngine defaultGeometryEngine];

self.distance = [geometryEngine geodesicLengthOfGeometry:sketchGeometry inUnit:AGSSRUnitMeter];

距離計算垂攘,單位是米淤刃。

AGSGeometry *sketchGeometry = measureSketchLayer.geometry;

AGSGeometryEngine *geometryEngine = [AGSGeometryEngine defaultGeometryEngine];

self.area = [geometryEngine shapePreservingAreaOfGeometry:sketchGeometry inUnit:AGSAreaUnitsSquareMeters];

面積計算,單位是平方米陨仅。

接下來介紹標(biāo)繪,包括點標(biāo)繪触徐、線標(biāo)繪狐赡、面標(biāo)繪、文字標(biāo)繪猾警。

創(chuàng)建方式:

//創(chuàng)建點

measureSketchLayer.geometry = [[AGSMutablePoint alloc] initWithX:NAN y:NAN spatialReference:self.mapView.spatialReference];

//創(chuàng)建線

measureSketchLayer.geometry = [[AGSMutablePolyline alloc] initWithSpatialReference:self.mapView.spatialReference];

//創(chuàng)建面

measureSketchLayer.geometry = [[AGSMutablePolygon alloc] initWithSpatialReference:self.mapView.spatialReference];

在AGSSketchGraphicsLayerGeometryDidChangeNotification的通知方法中发皿,更新點的信息。

如果你希望在點上面增加自定義視圖穴墅,可以這么寫:

self.mapView.callout.customView = antherView;

其中antherView,是我自己定義的一個視圖皇钞,比如在視圖上放個刪除按鈕松捉,放個label顯示數(shù)據(jù)等等,都可以可柿。

如果你想創(chuàng)建文字標(biāo)繪丙者,你需要這么寫:

AGSTextSymbol *textSymbol = [[AGSTextSymbol alloc] initWithText:self.plottingData.title

color:[UIColor redColor]];

textSymbol.fontFamily = @"Heiti SC";

textSymbol.vAlignment = AGSTextSymbolVAlignmentMiddle;

textSymbol.hAlignment = AGSTextSymbolHAlignmentCenter;

textSymbol.fontSize = 13;

textSymbol.offset = CGPointMake(0, 0);

AGSCompositeSymbol *compositeSymbol = [AGSCompositeSymbol compositeSymbol];

[compositeSymbol addSymbol:textSymbol];

AGSPoint *point_ags = [[AGSPoint alloc] initWithX:point.x y:point.y spatialReference:self.mapView.spatialReference];

AGSGraphic *graphic = [AGSGraphic graphicWithGeometry:point_ags symbol:compositeSymbol attributes:nil];

其中各種參數(shù)的含義,你通過英文的字面意思或者實際操作目锭,應(yīng)該都能理解纷捞。

有一個業(yè)務(wù)需求提到需要保存標(biāo)繪數(shù)據(jù),研究發(fā)現(xiàn)AGSGeometry實現(xiàn)了AGSCoding協(xié)議奖唯,可以將AGSGeometry對象轉(zhuǎn)成NSDictionary缀辩,這樣就可以使用歸檔保存在本地,歸檔類NSKeyedArchiver臀玄。

接下來介紹糾錯健无,路線規(guī)劃,運動累贤,搜索,離線地圖硼被。

糾錯需要讓地圖標(biāo)識符一直處于地圖的中點渗磅,調(diào)用的函數(shù)為:

CGPoint point = self.view.center;

AGSPoint *mapPoint = [self.mapView toMapPoint:point];

配合之前說的visibleAreaEnvelope就可以實現(xiàn)了。

路線規(guī)劃涉及到畫路線軌跡仔掸,先創(chuàng)建一個圖像層AGSGraphicsLayer医清,然后創(chuàng)建直線,或者在直線終點創(chuàng)建點会烙。

//創(chuàng)建直線持搜,添加路徑

AGSMutablePolyline *polyline = [[AGSMutablePolyline alloc] initWithSpatialReference:self.mapView.spatialReference];

[polyline addPathToPolyline];

//創(chuàng)建點,添加點路徑

AGSPoint *point = [AGSPoint pointWithX:x y:y spatialReference:self.mapView.spatialReference];

[polyline addPointToPath:point];

起點和終點的符號是由圖片和文字組成葫盼,你需要這么寫:

//創(chuàng)建一個圖片符號

AGSPictureMarkerSymbol *marker = [AGSPictureMarkerSymbol pictureMarkerSymbolWithImage:image];

//創(chuàng)建一個文字符號

AGSTextSymbol *textSymbol = [[AGSTextSymbol alloc] initWithText:text

color:[UIColor whiteColor]];

//然后創(chuàng)建一個AGSCompositeSymbol來加入這兩個符號贫导,如:

AGSCompositeSymbol *compositeSymbol = [AGSCompositeSymbol compositeSymbol];

[compositeSymbol addSymbol:marker];

[compositeSymbol addSymbol:textSymbol];

路線規(guī)劃的數(shù)據(jù)是通過請求服務(wù)端獲取的,獲取的數(shù)據(jù)有一定的格式孩灯,一般為分段的一系列點的集合峰档,需要根據(jù)約定好的規(guī)范進(jìn)行適配寨昙。

路線畫出來了掀亩,那么如何跳到路線所在位置的中心,你可以這么寫:

AGSMutableEnvelope *envelope = [routeGraphicsLayer.fullEnvelope mutableCopy];

[envelope expandByFactor:2.5];

[self.mapView zoomToEnvelope:envelope animated:YES];

說說運動:

運動中需要計步槽棍,計步采用加速度傳感器實現(xiàn),封裝了一個StepManager來管理步數(shù)缆巧,具體的算法就不細(xì)細(xì)展開豌拙,非本篇所講內(nèi)容。

運動需要在后臺長時間運行墩莫,需要申請后臺權(quán)限逞敷,上架的時候在備注中講清楚這個事,態(tài)度誠懇裂问,必要的時候叫蘋果幾聲爹牛柒,一般就沒什么問題了。

double distance = [geometryEngine geodesicLengthOfGeometry:lineGraphic.geometry inUnit:AGSSRUnitMeter];

運動采用的也是距離函數(shù)皮壁,保存上一點和下一點,然后規(guī)定一下距離超過5米或者10米時才畫直線虑瀑。

接下來說搜索滴须,

[self.mapView zoomToScale:self.mapView.mapScale withCenterPoint:(AGSPoint *)graphic.geometry animated:YES];

當(dāng)點擊搜索出來的紅色點時,或者點擊表格數(shù)據(jù)時痛侍,相應(yīng)的紅點要位于中心魔市。

搜索時需要與路線規(guī)劃對接赵哲,記住在程序設(shè)計的時候君丁,多抽離模塊代碼,避免相同模塊寫了兩份相同的代碼。

離線地圖比較簡單涧偷,就沒什么好說的了。需要注意的是這是個在后臺發(fā)起的下載任務(wù)喻鳄,而不是屬于某個控制器的下載任務(wù)确封,判斷好總大小,控制好節(jié)點數(shù)據(jù)颜曾,處理好暫停秉剑、繼續(xù),就沒什么問題了诡曙。

總結(jié):ArcGIS是定位最準(zhǔn)確的地圖略水,比高德和百度還準(zhǔn)確。但是缺點也是很明顯的渊涝,API封裝臃腫跨释,內(nèi)存消耗大,線程處理不夠優(yōu)美煤傍,地圖塊狀切割太大,用戶體驗不夠好等等五续。比起高德和百度地圖來說,還是差了一截凶伙。但是它碎,處理地圖的方式基本都是一致的,可以作為參考扳肛。

尾記:當(dāng)年研究的熱血涌上心頭挖息,不斷地自我突破,它是我1個人花了1個多月的時間做出來套腹,同樣的Deadline,安卓是兩個人做的幢码,還不算上我調(diào)通接口的時間尖飞。而且,論體驗和Bug率來說瓦糕,都屬上層腋么,最終讓地測院的人贊不絕口。

當(dāng)然圣勒,當(dāng)初的架構(gòu)還沒有使用到我文章列表的“iOS架構(gòu)”摧扇,代碼的結(jié)構(gòu)也非常的不優(yōu)美,但是注釋還是都有的吁峻。之所以出現(xiàn)這樣的問題,還是那句話:Deadline不是第一生產(chǎn)力用含,只是給了你把一堆Shit交上去的勇氣。

看完了痴鳄,不點個贊嗎缸夹?哈哈哈,隨便你橡类,開心就好趟妥。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末披摄,一起剝皮案震驚了整個濱河市勇凭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌虾标,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蘸吓,居然都是意外死亡,警方通過查閱死者的電腦和手機箩艺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門艺谆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拜英,“玉大人,你說我怎么就攤上這事』峙” “怎么了狰右?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵棋蚌,是天一觀的道長。 經(jīng)常有香客問我谷暮,道長湿弦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任蔬充,我火速辦了婚禮班利,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘罗标。我一直安慰自己闯割,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布证膨。 她就那樣靜靜地躺著鼓黔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪澳化。 梳的紋絲不亂的頭發(fā)上缎谷,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天灶似,我揣著相機與錄音瑞你,去河邊找鬼。 笑死春感,一個胖子當(dāng)著我的面吹牛虏缸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窥岩,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼宰缤,長吁一口氣:“原來是場噩夢啊……” “哼慨灭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起缘挑,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤语淘,失蹤者是張志新(化名)和其女友劉穎际歼,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吕粗,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡旭愧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年输枯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桃熄。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖厢汹,靈堂內(nèi)的尸體忽然破棺而出谐宙,到底是詐尸還是另有隱情,我是刑警寧澤卧惜,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布咽瓷,位于F島的核電站,受9級特大地震影響茅姜,放射性物質(zhì)發(fā)生泄漏钻洒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一称诗、第九天 我趴在偏房一處隱蔽的房頂上張望头遭。 院中可真熱鬧,春花似錦计维、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赏淌。三九已至,卻和暖如春猜敢,著一層夾襖步出監(jiān)牢的瞬間盒延,已是汗流浹背鼠冕。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工懈费, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人票罐。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓泞边,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蚕礼。 傳聞我的和親對象是個殘疾皇子梢什,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容