你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 使用蘋果自帶地圖獲取當前位置及周圍信息

使用蘋果自帶地圖獲取當前位置及周圍信息

編輯:IOS開發基礎

天朝的網絡在XXX的干預下,我們很多內容都不能正常訪問,需要翻牆。處在這樣一個大的局域網環境之下,作為IT行業的我們很是苦惱,如果做的應用要世界通用,那就是痛苦了,需要考慮很多。例如:如果我們做一個地圖應用,兼容中國和外國。要麼使用國內地圖+Google,要麼就是使用蘋果自帶地圖。今天主要介紹使用蘋果自帶地圖獲取用戶當前位置及用戶周圍信息,地圖移動時,地圖中間指針一直在中間,移動結束後有下落定位的動畫效果並更新當前位置及用戶周圍信息。需要真機測試查看效果。

先看效果:
gif動畫是在模擬器上錄制,由於模擬器不能獲取周圍信息,所以一直在轉菊花。要看實際效果需要真機查看。

2926059-f77b1aab8779e5dc.gif

2926059-038582bd5b5c11aa.PNG

步驟

添加庫MapKit.framework

2926059-128ced5cff4c3095.png

模擬器效果展示

打開地圖功能。

2926059-bcaac77390f0f8a4.png

真機截圖
  1. 代碼實現。

  2. 在用戶位置顯示完成後添加一個固定的ImageView在地圖正中間。

-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    NSLog(@"userLocation:longitude:%f---latitude:%f",userLocation.location.coordinate.longitude,userLocation.location.coordinate.latitude);
    if (!haveGetUserLocation) {
        if (self.mapView.userLocationVisible) {
            haveGetUserLocation = YES;
            [self getAddressByLatitude:userLocation.coordinate.latitude longitude:userLocation.coordinate.longitude];
            [self addCenterLocationViewWithCenterPoint:self.mapView.center];
        }

    }
}


-(void)addCenterLocationViewWithCenterPoint:(CGPoint)point
{
    if (!imgView) {
        imgView = [[UIImageView alloc]initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width/2, 100, 18, 38)];
        imgView.center = point;
        imgView.image = [UIImage imageNamed:@"map_location"];
        imgView.center = self.mapView.center;
        [self.view addSubview:imgView];
    }

}
  • 獲取當前位置周圍信息,蘋果提供了一個請求方法,MKLocalSearch。其官方介紹為:

    An MKLocalSearch object initiates a map-based search operation and delivers the results back to your app asynchronously. Search objects are designed to perform one search operation only. To perform several different searches, you must create separate instances of this class and start them separately.
    也就是說我們如果要搜索不同的類型需要分別創建多個實例進行操作。

如果我們要搜索周圍100米餐廳代碼如下:

MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coordinate,100, 100);
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc]init];
request.region = region;
request.naturalLanguageQuery = @"Restaurants";
MKLocalSearch *localSearch = [[MKLocalSearch alloc]initWithRequest:request];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error){
     if (!error) {
            //do something.
     }else{
            //do something.
     }
 }];

其中naturalLanguageQuery就是要搜索的關鍵字,我試過的所有關鍵字有cafe, supermarket,village,Community,Shop,Restaurant,School,hospital,Company,Street,Convenience store,Shopping Centre,Place names,Hotel,Grocery store每個關鍵字搜索返回結果只有10條,如果當前范圍無搜索結果,則擴散搜索范圍。如果你想列出周圍所有相關位置信息,我認為需要盡可能的把所有的能夠想到的關鍵字都舉例出來進行搜索,搜索完成後進行經緯度比較然後刷選出范圍內的相關位置。而且由於數據來源問題,很多位置信息都沒有!當然如果你只兼容國內,還是使用百度或者騰訊地圖算了。

  • 根據經緯度獲取位置相關信息。

CLLocation *location=[[CLLocation alloc]initWithLatitude:latitude longitude:longitude];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
        if (!error) {
            dispatch_async(dispatch_get_main_queue(), ^{
            //do something.
            });
        }else{
            //do something.
        }

    }];
  • 下落定位動畫效果

imgView.center = CGPointMake(mapCenter.x, mapCenter.y-15);
        [UIView animateWithDuration:0.2 animations:^{
            imgView.center = mapCenter;
        }completion:^(BOOL finished){
            if (finished) {
                [UIView animateWithDuration:0.05 animations:^{
                    imgView.transform = CGAffineTransformMakeScale(1.0, 0.8);

                }completion:^(BOOL finished){
                    if (finished) {
                        [UIView animateWithDuration:0.1 animations:^{
                            imgView.transform = CGAffineTransformIdentity;
                        }];
                    }
                }];

            }
        }];

這裡我的思路是三個動畫效果組合以達到大頭針下落定位的效果。

  • 獲取用戶滑動地圖操作。
    MKMapViewDelegate中有個方法在滑動結束後可以回調如下所示:

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated

因為回調是在展示的地圖區域改變後調用,所以使用它有個缺點就是在最開始初始化地圖並定位到用戶所在位置時,它會被反復回調。所以很難確定用戶是否是滑動。所以這裡我們需要知道用戶是否和地圖有過滑動後導致它的回調。如何做呢?這裡有兩種方法以供參考。
方法一:這裡你是否想起UIScrollView,如果我們想獲取touch事件,我們應該怎麼做,沒錯就是繼承後重寫touch方法,然後把toush事件傳遞下去。代碼如下:

@implementation ZHMapView

#pragma mark - touchs
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    [[self nextResponder] touchesBegan:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];
    [[self nextResponder] touchesMoved:touches withEvent:event];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    [[self nextResponder] touchesEnded:touches withEvent:event];

}

- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event
{
     [super touchesCancelled:touches withEvent:event];
    [[self nextResponder]touchesCancelled:touches withEvent:event];
}

方法二:我在修改 navigationBar 底部線條顏色總結這篇文章中有用到查看View層次結構找到隱藏屬性並對它進行操作。沒錯這裡也是一樣的道理,先看mapview層次結構例如如下所示:

2926059-1b05bfa9cd4e7829.png


這裡我們可以發現_MKMapContentView裡面有個手勢數組,沒錯就是它了。我們獲取它並對他進行操作,代碼如下所示:

//打印完後我們發現有個View帶有手勢數組其類型為_MKMapContentView獲取Span手勢
    for (UIView *view in self.mapView.subviews) {
        NSString *viewName = NSStringFromClass([view class]);
        if ([viewName isEqualToString:@"_MKMapContentView"]) {
            UIView *contentView = view;//[self.mapView valueForKey:@"_contentView"];
            for (UIGestureRecognizer *gestureRecognizer in contentView.gestureRecognizers) {
                if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
                    [gestureRecognizer addTarget:self action:@selector(mapViewSpanGesture:)];
                }
            }

        }
    }
  • 加載時UITableView頂部展示菊花展示,這個原理和我們做分頁展示時,滑動到底部或頂部有個菊花展示的道理一樣。代碼如下

#pragma mark - Private Methods
-(void)resetTableHeadView
{
    if (infoArray.count>0) {
        self.showTableView.tableHeaderView = nil;
    }else{
        UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 30.0)];
        view.backgroundColor = self.showTableView.backgroundColor;
        UIActivityIndicatorView *indicatorView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        indicatorView.center = view.center;
        [indicatorView startAnimating];
        [view addSubview:indicatorView];
        self.showTableView.tableHeaderView = view;

    }
}

下載地址

GitHub

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved