Core Location和MapKit的一些简单使用

本文详细介绍了iOS开发中地理位置定位(CoreLocation)及地图显示(MapKit)的技术要点,包括CLLocationManager的配置与使用、不同位置服务的特点、地理编码实现、MKMapView的定制化展示等。

Core Location

1. 基本对象是CLLocation,有属性coordinate, altitude, horizontal/vertical Accuracy, timestamp, speed, course

typedef {
CLLocationDegrees latitude; // a double
CLLocationDegrees longitude; // a double 
} CLLocationCoordinate2D;    // 经纬度

@property (readonly) CLLocationAccuracy horizontalAccuracy; // in meters 
@property (readonly) CLLocationAccuracy verticalAccuracy;

kCLLocationAccuracyBestForNavigation;
kCLLocationAccuracyBest;
kCLLocationAccuracyNearestTenMeters;
kCLLocationAccuracyHundredMeters;
kCLLocationAccuracyKilometer;
kCLLocationAccuracyThreeKilometers;


- (CLLocationDistance)distanceFromLocation:(CLLocation *)otherLocation; // in meters 两个位置之间的距离


2. 总是通过CLLocationManager来获取CLLocation(通过其代理),其一般的使用方法为:

(1)检查硬件是否支持你需要的位置更新

(2)创建一个CLLocationManager实例,并设置接收更新的代理对象

(3)根据你的需求对CLLocationManager进行配置

(4)启动CLLocationManager来监视改变。


3. Core Location Manager的一些设置

@property CLLocationAccuracy desiredAccuracy; // always set this as low as possible 
@property CLLocationDistance distanceFilter; 

- (void)startUpdatingLocation;
- (void)stopUpdatingLocation;

- (void)startMonitoringSignificantLocationChanges;
- (void)stopMonitoringSignificantLocationChanges;


Core Location框架提供了三种用于追踪设备当前位置的服务

  • The significant-change location 

    service 提供了低耗电的方法来获取当前位置,当前位置改变时会发出通知
  • The standard location service 提供了一种可设置的方法来获取当前位置

  • Region monitoring 监视特定地区的跨越

Listing 1  Starting the standard location service
- (void)startStandardUpdates
{
    // 创建location manager
    if (nil == locationManager)
        locationManager = [[CLLocationManager alloc] init];
 
    locationManager.delegate = self;

  // 设置获取位置的精确度,越精确越耗电
    locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
 
    // 设置距离过滤器,超过次距离就更新一次位置
    locationManager.distanceFilter = 500;
 
    [locationManager startUpdatingLocation];
}

Listing 2 Significant-Change Location Service

- (void)startSignificantChangeUpdates
{
    // Create the location manager if this object does not
    // already have one.
    if (nil == locationManager)
        locationManager = [[CLLocationManager alloc] init];
 
    locationManager.delegate = self;
    [locationManager startMonitoringSignificantLocationChanges];
}

4. 检查硬件

+ (BOOL)locationServicesEnabled; // has the user enabled location monitoring in Settings? 
+ (BOOL)headingAvailable; // can this hardware provide heading info (compass)? 
+ (BOOL)significantLocationChangeMonitoringAvailable; // only if device has cellular?
+ (BOOL)regionMonitoringAvailable; // only certain iOS4 devices
+ (BOOL)regionMonitoringEnabled; // by the user in Settings

当程序初次使用位置服务时,会询问用户。可以提供一个string来描述使用目的。如果用户拒绝,则上面所有方法均返回NO

 @property (copy) NSString *purpose


5. 获取位置更新

// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation
{
    // If it's a relatively recent event, turn off updates to save power
    NSDate* eventDate = newLocation.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    if (abs(howRecent) < 15.0)
    {
        NSLog(@"latitude %+.6f, longitude %+.6f\n",
                newLocation.coordinate.latitude,
                newLocation.coordinate.longitude);
    }
    // else skip the event and process the next one.
}

- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error;

typedef enum {
   kCLErrorLocationUnknown  = 0,
   kCLErrorDenied,                           // 如果用户拒绝开启位置服务,那么应该停止location manager
   kCLErrorNetwork,
   kCLErrorHeadingFailure,
   kCLErrorRegionMonitoringDenied,
   kCLErrorRegionMonitoringFailure,
   kCLErrorRegionMonitoringSetupDelayed,
} CLError;


6. Geocoding Location Data

Geocoder对象使用网络服务来将经纬度转换为具体地址信息,iOS当前只支持经纬度转地址信息,不能将位置信息转换为经纬度

创建一个MKReverseGeocoder实例,设置代理,调用start方法。
代理会接受到 reverseGeocoder:didFindPlacemark:和reverseGeocoder:didFailWithError:


@implementation MyGeocoderViewController (CustomGeocodingAdditions)  
- (void)geocodeLocation:(CLLocation*)location forAnnotation:(MapLocation*)annotation  
{  
    MKReverseGeocoder* theGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:location.coordinate];  
   
    theGeocoder.delegate = self;  
    [theGeocoder start];  
}  
   
// Delegate methods  
- (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFindPlacemark:(MKPlacemark*)place  
{  
    MapLocation*    theAnnotation = [map annotationForCoordinate:place.coordinate];  
    if (!theAnnotation)  
        return;  
   
   // Associate the placemark with the annotation.  
    theAnnotation.placemark = place;  
   
    // Add a More Info button to the annotation's view.  
    MKPinAnnotationView*  view = (MKPinAnnotationView*)[map viewForAnnotation:annotation];  
    if (view && (view.rightCalloutAccessoryView == nil))  
    {  
        view.canShowCallout = YES;  
        view.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];  
    }  
}  
   
- (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFailWithError:(NSError*)error  
{  
    NSLog(@"Could not retrieve the specified place information.\n");  
}  
@end  
   
@implementation MKMapView (GeocoderAdditions)  
   
- (MapLocation*)annotationForCoordinate:(CLLocationCoordinate2D)coord  
{  
    // Iterate through the map view's list of coordinates  
    // and return the first one whose coordinate matches  
    // the specified value exactly.  
    id<MKAnnotation> theObj = nil;  
   
    for (id obj in [self annotations])  
    {  
        if (([obj isKindOfClass:[MapLocation class]]))  
        {  
            MapLocation* anObj = (MapLocation*)obj;  
   
            if ((anObj.coordinate.latitude == coord.latitude) &&  
                (anObj.coordinate.longitude == coord.longitude))  
            {  
                theObj = anObj;  
                break;  
            }  
        }  
    }  
  
    return theObj;  
}  
@end



MapKit

1. MKMapView 显示地图

2. 地图上可以显示注释(annotation),每个annotation由coordinate,title,subtitle构成,并由MKAnnotationView来显示

3. Annotation可以有一个callout,当annotation view被点击时显示,默认情况下只是显示title和subtitle,不过你可以添加左右accessory views

4. MKMapView显示一个遵守MKAnnotation协议的数组对象

@property (readonly) NSArray *annotations; // contains id <MKAnnotation> objects
MKAnnotation protocol
@protocol MKAnnotation <NSObject>
@property (readonly) CLLocationCoordinate2D coordinate;
@optional
@property (readonly) NSString *title;
@property (readonly) NSString *subtitle;
@end
typedef {
    CLLocationDegrees latitude;
    CLLocationDegrees longitude;
} CLLocationCoordinate2D;




5. 管理map view的annotations的方法

- (void)addAnnotation:(id <MKAnnotation>)annotation;
- (void)addAnnotations:(NSArray *)annotations;
- (void)removeAnnotation:(id <MKAnnotation>)annotation;
- (void)removeAnnotations:(NSArray *)annotations;

6. MKMapView使用跟TableView类似的方法来重用annotation view

7. Annotations通过MKAnnotationView的子类显示在地图上,默认为MKPinAnnotationView

8. 如果MKAnnotationView的canShowCallout设置为YES,那么点击会显示,同时会调用

- (void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView;
//This is a great place to set up the MKAnnotationView‘s callout accessory views lazily.

9. MKAnnotationViews的创建方法跟tableviewcell在tableview中的创建类似

- (MKAnnotationView *)mapView:(MKMapView *)sender
            viewForAnnotation:(id <MKAnnotation>)annotation
{
    MKAnnotationView *aView = [sender dequeueReusableAnnotationViewWithIdentifier:IDENT];
    if (!aView) {
        aView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
                                                reuseIdentifier:IDENT];
        // set canShowCallout to YES and build aView’s callout accessory views here 
             }
    aView.annotation = annotation; // yes, this happens twice if no dequeue
    // maybe load up accessory views here (if not too expensive)?
    // or reset them and wait until mapView:didSelectAnnotationView: to load actual data
    return aView;
}

10. MKAnnotationView的一些属性

@property id <MKAnnotation> annotation; // the annotation; treat as if readonly 
@property UIImage *image; // instead of the pin, for example
@property UIView *leftCalloutAccessoryView; // maybe a UIImageView
@property UIView *rightCalloutAccessoryView; // maybe a “disclosure” UIButton 
@property BOOL enabled; // NO means it ignores touch events, no delegate method, no callout 
@property CGPoint centerOffset; // where the “head of the pin” is relative to the image 
@property BOOL draggable; // only works if the annotation implements setCoordinate:

11. 如果你设置一个callout accessory view为一个UIControl

e.g. aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 
The following MKMapViewDelegate method will get called when the accessory view is touched ...

- (void)mapView:(MKMapView *)sender 
        annotationView:(MKAnnotationView *)aView
        calloutAccessoryControlTapped:(UIControl *)control;

12. 使用一下代理方法来加载accessory views

-(void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView 
{
   if ([aView.leftCalloutAccessoryView isKindOfClass:[UIImageView class]]) {
          UIImageView *imageView = (UIImageView *)aView.leftCalloutAccessoryView; 
          imageView.image = ...; // if you do this in a GCD queue, be careful, views are reused!
   }
}

13. 地图类型

@property MKMapType mapType;
enum {  
    MKMapTypeStandard = 0,  
    MKMapTypeSatellite,  
    MKMapTypeHybrid  
};  
typedef NSUInteger MKMapType;  



14. 显示用户当前地址

@property BOOL showsUserLocation;
@property (readonly) BOOL isUserLocationVisible;
@property (readonly) MKUserLocation *userLocation;
MKUserLocation is an object which conforms to MKAnnotation which holds the user’s location.

15.限制用户对地图的操作

@property BOOL zoomEnabled;
@property BOOL scrollEnabled;

16. 控制地图的显示区域

@property MKCoordinateRegion region;
typedef struct {
    CLLocationCoordinate2D center;
    MKCoordinateSpan span;
} MKCoordinateRegion;

typedef struct {
    CLLocationDegrees latitudeDelta;
    CLLocationDegrees longitudeDelta;
}
- (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated; // animate
注意:
你赋给region属性的值通常不是最终保存的值,在设置显示区域的时候同时也设置了缩放等级。map view不能显示任意的缩放等级,因此map view会选择一个能够尽可能显示你指定区域大小的缩放等级,然后根据此时显示的区域来保存。

@property CLLocationCoordinate2D centerCoordinate;
- (void)setCenterCoordinate:(CLLocationCoordinate2D)center animated:(BOOL)animated;

17. 地图载入通知

Remember that the maps are downloaded from Google earth.
- (void)mapViewWillStartLoadingMap:(MKMapView *)sender;
- (void)mapViewDidFinishLoadingMap:(MKMapView *)sender;
- (void)mapViewDidFailLoadingMap:(MKMapView *)sender withError:(NSError *)error;

18.








智慧医药系统(smart-medicine)是一款采用SpringBoot架构构建的Java Web应用程序。其界面设计简洁而富有现代感,核心特色在于融合了当前前沿的生成式人工智能技术——具体接入了阿里云的通义千问大型语言模型,以此实现智能医疗咨询功能,从而增强系统的技术先进性与实用价值。该系统主要定位为医学知识查询与辅助学习平台,整体功能结构清晰、易于掌握,既适合编程初学者进行技术学习,也可作为院校课程设计或毕业项目的参考实现。 中医舌诊作为传统医学的重要诊断手段,依据舌象的颜色、形状及苔质等特征来辨析生理状况与病理变化。近年来,随着计算科学的进步,人工智能技术逐步渗透到这一传统领域,形成了跨学科的研究与应用方向。所述的中医舌诊系统正是这一方向的实践产物,它运用AI算法对舌象进行自动化分析。系统以SpringBoot为基础框架,该框架依托Java语言,致力于简化Spring应用程序的初始化与开发流程,其突出优势在于能高效构建独立、可投入生产的应用,尤其契合微服务架构与云原生环境,大幅降低了开发者在配置方面的负担。 系统中整合的通义千问大语言模型属于生成式人工智能范畴,通过海量数据训练获得模拟人类语言的能力,可在限定领域内生成连贯文本,为用户提供近似专业医生的交互式咨询。该技术的引入有助于提升诊断过程的自动化水平与结果一致性。 在设计与体验层面,本系统强调逻辑明晰与操作简便,旨在降低用户的学习门槛,尤其适合中医知识的入门教学。整体交互模式接近百科全书式查询,功能模块精炼聚焦,因而非常适用于教育场景,例如学术项目展示或毕业设计答辩。通过直观的实践界面,使用者能够更深入地理解中医舌诊的理论与方法。 此外,系统界面遵循简约大气的设计原则,兼顾视觉美感与交互流畅性,以提升用户的专注度与使用意愿。结合AI的数据处理能力,系统可实现对舌象特征的快速提取与实时分析,这不仅为传统诊断方法增添了客观量化维度,也拓展了中医知识传播的途径。借助网络平台,该系统能够突破地域限制,使更多用户便捷地获取专业化的中医健康参考,从而推动传统医学在现代社会的应用与普及。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
【掺铒光纤放大器(EDFA)模型】掺铒光纤放大器(EDFA)分析模型的模拟研究(Matlab代码实现)内容概要:本文介绍了掺铒光纤放大器(EDFA)分析模型的模拟研究,并提供了基于Matlab的代码实现方案。通过对EDFA的工作原理、增益特性、噪声系数等关键性能指标进行数学建模与仿真分析,帮助研究人员深入理解其在光通信系统中的作用机制。文档还列举了多个相关科研方向的技术支持内容,涵盖智能优化算法、路径规划、无人机应用、通信与信号处理、电力系统管理等多个领域,展示了Matlab在科学研究与工程仿真中的广泛应用能力。此外,文中附带网盘链接,便于获取完整的代码资源与开发工具包。; 适合人群:具备一定光学通信或电子信息背景,熟悉Matlab编程,从事科研或工程仿真的研究生、高校教师及技术研发人员。; 使用场景及目标:①用于光通信系统中EDFA性能的理论分析与仿真验证;②支持科研人员快速构建测试EDFA模型,提升研究效率;③为教学实验、毕业设计及学术论文复现提供可靠的技术参考与代码基础。; 阅读建议:建议读者结合光通信基础知识,按照文档结构逐步运行并调试Matlab代码,重点关注模型参数设置与仿真结果分析,同时可利用提供的网盘资源拓展学习其他相关课题,深化对系统级仿真的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值