天朝的網(wǎng)絡在XXX的干預下,我們很多內(nèi)容都不能正常訪問,需要翻墻惠啄。處在這樣一個大的局域網(wǎng)環(huán)境之下,作為IT行業(yè)的我們很是苦惱,如果做的應用要世界通用,那就是痛苦了,需要考慮很多饿敲。例如:如果我們做一個地圖應用,兼容中國和外國。要么使用國內(nèi)地圖+Google困介,要么就是使用蘋果自帶地圖。今天主要介紹使用蘋果自帶地圖獲取用戶當前位置及用戶周圍信息,地圖移動時,地圖中間大頭針一直在中間,移動結束后有下落定位的動畫效果并更新當前位置及用戶周圍信息疫剃。需要真機測試查看效果仍侥。
先看效果:
gif動畫是在模擬器上錄制,由于模擬器不能獲取周圍信息捉偏,所以一直在轉(zhuǎn)菊花雷激。要看實際效果需要真機查看替蔬。
步驟
-
添加庫
MapKit.framework
告私。
模擬器效果展示 -
打開地圖功能屎暇。
真機截圖 代碼實現(xiàn)。
- 在用戶位置顯示完成后添加一個固定的
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.
也就是說我們?nèi)绻阉鞑煌念愋托枰謩e創(chuàng)建多個實例進行操作。
如果我們要搜索周圍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條琴昆,如果當前范圍無搜索結果,則擴散搜索范圍。如果你想列出周圍所有相關位置信息馆揉,我認為需要盡可能的把所有的能夠想到的關鍵字都舉例出來進行搜索业舍,搜索完成后進行經(jīng)緯度比較然后刷選出范圍內(nèi)的相關位置。而且由于數(shù)據(jù)來源問題升酣,很多位置信息都沒有舷暮!當然如果你只兼容國內(nèi),還是使用百度或者騰訊地圖算了噩茄。
- 根據(jù)經(jīng)緯度獲取位置相關信息下面。
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
中有個方法在滑動結束后可以回調(diào)如下所示:
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
因為回調(diào)是在展示的地圖區(qū)域改變后調(diào)用诸狭,所以使用它有個缺點就是在最開始初始化地圖并定位到用戶所在位置時,它會被反復回調(diào)。所以很難確定用戶是否是滑動君纫。所以這里我們需要知道用戶是否和地圖有過滑動后導致它的回調(diào)驯遇。如何做呢?這里有兩種方法以供參考蓄髓。
方法一:這里你是否想起UIScrollView
,如果我們想獲取touch
事件叉庐,我們應該怎么做,沒錯就是繼承后重寫touch
方法会喝,然后把toush
事件傳遞下去陡叠。代碼如下:
@implementation ZHMapView
#pragma mark - touchs
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
[[self nextResponder] touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
[[self nextResponder] touchesMoved:touches withEvent:event];
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
[[self nextResponder] touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
[[self nextResponder]touchesCancelled:touches withEvent:event];
}
方法二:我在修改 navigationBar 底部線條顏色總結這篇文章中有用到查看View層次結構找到隱藏屬性并對它進行操作玩郊。沒錯這里也是一樣的道理,先看mapview層次結構例如如下所示:
這里我們可以發(fā)現(xiàn)
_MKMapContentView
里面有個手勢數(shù)組枉阵,沒錯就是它了译红。我們獲取它并對他進行操作,代碼如下所示:
//打印完后我們發(fā)現(xiàn)有個View帶有手勢數(shù)組其類型為_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;
}
}