MKMapViewに境界を実装する簡単な方法を知っている人は誰でもいます。たとえば、地図に1つのエリアにしか滞在できないことを伝えたいと思います。ユーザーがスクロールできるようにしたいのですが、特定の緯度/経度に達したときに停止させます。willChangeRegion:デリゲートを使用してみましたが、失敗しました。ありがとう。
3 に答える
これについてブログに投稿しました。こちらをご覧ください:http://blog.jamgraham.com/blog/2012/04/29/adding-boundaries-to-mkmapview/
MKMapViewの境界をロックする必要があるプロジェクトに取り組みました。アップルが提供するすぐに使えるソリューションがないため、MKMapViewのサブクラス化が残っています。これは非常に簡単で、マップにあるUIScrollViewやMKMapViewの他の楽しいオブジェクトにアクセスできます。
今すぐコードを見たいですか?ここから入手できます:https ://github.com/jamgraham/geoFencer
MKMapViewの境界をロックすると、2つの一般的な手順が呼び出されます。まず、ズームレベルを最小値と最大値にロックします。2つ目は、作成したファウンドリの外でユーザーがスクロールできないようにすることです。オーバーライドする必要のあるデリゲートを見て、これらを見ていきましょう
1.ズームレベル
これは非常に簡単です。目標は、ユーザーがズームするときにズームレベルを確認し、ユーザーがズームを停止したときにもう一度確認することです。
-(void)scrollViewDidZoom:(UIScrollView *)scrollView;
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
2.スクロール境界
これはもう少し複雑です。ユーザーがUIScrollViewでマップをスクロールするときに、境界の外に出ないようにし、外に出ない場合は停止します。これは、ユーザーが境界の外に出たときにマップを境界に再配置することで実現できます。これは、ユーザーが地図をぐいと動かしているのではなく、壁にぶつかったように感じる場合に十分な速さで発生します。監視する必要のある代表者は次のとおりです。
-(void)scrollViewDidScroll:(UIScrollView *)scrollView;
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
3.コピー&ペースト
以下のカスタムMKMapViewをコピーして貼り付けてください。マップを表示するUIViewControllerで、カスタムマップビューに境界を設定する必要があります
ViewController.m
//Set map boundaries
mapView.showsUserLocation = YES;
[mapViewsetZoomMax:0.015551];
[mapViewsetZoomMin: 0.346360];
mapView.top = 37.773498;
mapView.bottom = 37.745130;
mapView.left = -122.430365;
mapView.right = -122.401623;
GeoMapView.h
@interface GeoMapView : MKMapView
{
MKCoordinateRegion cordRegion;
CLLocationCoordinate2D oldcenter;
double left;
double right;
double top;
double bottom;
double zoomMax;
double zoomMin;
}
-(void)checkZoom;
-(void)checkScroll;
@property (nonatomic) double left;
@property (nonatomic) double right;
@property (nonatomic) double top;
@property (nonatomic) double bottom;
@property (nonatomic) double zoomMax;
@property (nonatomic) double zoomMin;
@end
GeoMapView.m
#import "GeoMapView.h"
@implementation GeoMapView
@synthesize left, right, top, bottom,zoomMax,zoomMin;
- (id)initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];
if (self) {
}
returnself;
}
-(void)scrollViewDidZoom:(UIScrollView *)scrollView {
[selfcheckZoom];
}
-(void)checkZoom{
UIScrollView * scroll = [[[[selfsubviews] objectAtIndex:0] subviews] objectAtIndex:0];
if (scroll.zoomScale < zoomMax) {
NSLog(@"Reached Max Zoom");
[scroll setZoomScale:zoomMaxanimated:NO];
}
if (scroll.zoomScale >= zoomMin) {
NSLog(@"Reached Min Zoom");
[scroll setZoomScale:zoomMinanimated:NO];
}
}
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
UIScrollView * scroll = [[[[selfsubviews] objectAtIndex:0] subviews] objectAtIndex:0];
if (scroll.zoomScale > zoomMin) {
[scroll setZoomScale:zoomMinanimated:NO];
}
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
[selfcheckScroll];
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
[selfcheckScroll];
}
-(void)checkScroll{
@try{
cordRegion = self.region;
CLLocationCoordinate2D center = self.region.center;
CLLocationCoordinate2D northWestCorner, southEastCorner;
northWestCorner.latitude = center.latitude + (self.region.span.latitudeDelta / 2.0);
northWestCorner.longitude = center.longitude - (self.region.span.longitudeDelta / 2.0);
southEastCorner.latitude = center.latitude - (self.region.span.latitudeDelta / 2.0);
southEastCorner.longitude = center.longitude + (self.region.span.longitudeDelta / 2.0);
CLLocationCoordinate2D newcenter;
newcenter.latitude = self.region.center.latitude;
newcenter.longitude = self.region.center.longitude;
//LEFT
CLLocationDegrees farLeft = left;
CLLocationDegrees snapToLeft = farLeft + (self.region.span.longitudeDelta / 2.0);
if (northWestCorner.longitude < farLeft)
{
newcenter.longitude = snapToLeft;
cordRegion = self.region;
}
//RIGHT
CLLocationDegrees r = (self.region.span.longitudeDelta / 2.0);
CLLocationDegrees farRight = right;
CLLocationDegrees snapToRight = farRight - r;
if (southEastCorner.longitude > farRight)
{
newcenter.longitude = snapToRight;
}
//TOP
CLLocationDegrees farTop = top;
CLLocationDegrees snapToTop = top - (self.region.span.latitudeDelta / 2.0);
if (northWestCorner.latitude > farTop)
{
newcenter.latitude = snapToTop;
}
//BOTTOM
CLLocationDegrees farBottom = bottom;
CLLocationDegrees rr = (self.region.span.latitudeDelta / 2.0);
CLLocationDegrees snapToBottom = bottom + rr;
if (southEastCorner.latitude < farBottom)
{
newcenter.latitude = snapToBottom;
}
[selfsetCenterCoordinate:newcenter animated:NO];
}
@catch (NSException *e) {
}
@finally {}
}
@end
アイデア
現在、ジオフェンスでは多くのすばらしいことが行われています。いくつかのアイデア:
- 住所を入力し、地図をその住所にロックします
- マップオーバーレイを使用したジオフェンス
- ユーザーが実際にそれらの物理的な場所を訪れたときにマップの領域のロックを解除する物理的なゲーム。
だから私は先に進んで自分の質問に答え、この振る舞いを実装する簡単な方法はないと言います。境界を確認する必要があるだけでなく、スクロールの方向も確認する必要があります。コンソールは、スクロール後の最後のタッチですが、scrollViewDidEndDragging:willDecelerate:が呼び出されなかったことを通知し続けます。やるべきことはもっとたくさんあると思います...
私はいくつかの調査を行ってきましたが、それを行う簡単な方法はないことがわかりました。
したがって、私の解決策は、マップを特定の領域にロックし、MKMapViewを含むscrollViewを使用してズームインおよびズームアウトすることです。