Contenu connexe Similaire à 05 MapKit and Text Input Similaire à 05 MapKit and Text Input (20) 05 MapKit and Text Input2. • 在这⼀一章,我们将使⽤用 MapKit 框架,UITextField
类以及更多的 delegation 来完成 Whereami 应⽤用。
• ⺫⽬目前,whereami 找到位置并且在控制台打印出
来。这章结束时,应⽤用程序将显⽰示出当前位置的
地图.并且⽤用户还有⼀一个可选项,可以使⽤用MapKit
annotation 标记和命名当前的位置。默认的
MapKit annotation 显⽰示为地图上的⼀一个红⾊色的⼤大
头针。
5. view objects
• MKAnnotationView
• 在 MKMapView 上作为图标显⽰示的⼏几个
MKAnnotationView 的实例
• MKMapView
• 显⽰示地图,和所记录的位置的标签
• UIActivityIndicatorView
• 表⽰示当前设备还在⼯工作,没有⽌止步不前
• UITextField
• 允许⽤用户输⼊入⽂文本来给地图上的当前位置打标签
7. controller object
• WhereamiViewController
• 负责处理来⾃自其他对象的更新和请求
• 是 MKMapView 的 delegate
• 当⼀一个 view 或者多个 views 被添加上以后 MKMapView 会发
送 mapView:didAddAnnotationViews:
• 是 UITextField 的 delegate
• ⽤用户完成输⼊入⽂文本后,UITextField 会发送
textFieldShouldReturn:
• 是 CLLocationManager 的 delegate
• 发送 locationManager:didUpdateLocations: 通知
WhereamiViewController 位置已经更新
8. MapKit 框架
• Core Location framework 告诉我们我们在世界上
的什么地⽅方
• MapKit framework 把世界显⽰示给我们
• MapKit 的主要⼯工作都是由 MKMapView 类完成的
• 显⽰示⼀一个地图
• 追踪触控
• 以及显⽰示注释(annotation)
10. 导⼊入 MapKit 头⽂文件
#import <UIKit/UIKit.h>
// 导⼊入 Core Location framework 的头⽂文件
#import <CoreLocation/CoreLocation.h>
// 导⼊入MapKit framework 的头⽂文件
#import <MapKit/MapKit.h>
11. 声明必要的实例变量
@interface WhereamiViewController : UIViewController
<CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
IBOutlet MKMapView *worldView;
IBOutlet UIActivityIndicatorView *activityIndicator;
IBOutlet UITextField *locationTitleField;
}
@end
12. 界⾯面属性(Interface Properties)
1.从界⾯面右侧的 object library 中拖拽 MKMapView 到
UIView 上
2.再拖拽 UITextField, UIActivityIndicatorView 到
MKMapView 上,适当调整位置和⼤大⼩小
3.设置 ViewController 中实例变量到新增加的视图的
链接(IBOutlet指⽰示的)
4.设置新增加的视图的 delegate 到 ViewController
17. 作为 MapView 的 Delegate
• 我们希望 Whereami 启动时,找到当前的位置并在
地图上显⽰示
• 上⼀一个主题我们直接使⽤用 Core Location 查找⽤用户
的位置
• MKMapView 实例本⾝身知道如何使⽤用 Core Location
查找⽤用户位置
• 设置 MKMapView 的 showUserLocation 属性为 YES,
然后它就会查找⽤用户的位置并把它显⽰示在地图上
• 界⾯面加载完以后,WhereamiViewController 会被发送
viewDidLoad 消息,我们在这⾥里⾯面告诉 MKMapView 来
更新它的位置。
18. 修改 WhereamiViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
! // Do any additional setup after loading the view, typically from a nib.
[worldView setShowsUserLocation:YES];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationManager startUpdatingLocation];
}
return self;
}
23. MKCoordinateRegion
typedef struct {
! CLLocationCoordinate2D center;
! MKCoordinateSpan span;
} MKCoordinateRegion;
typedef struct {
! CLLocationDegrees latitude;
! CLLocationDegrees longitude;
} CLLocationCoordinate2D;
typedef struct {
CLLocationDegrees latitudeDelta;
CLLocationDegrees longitudeDelta;
} MKCoordinateSpan;
typedef double CLLocationDegrees;
24. MKUserLocation
@interface MKUserLocation : NSObject <MKAnnotation> {
@private
MKUserLocationInternal *_internal;
}
// Returns YES if the user's location is being updated.
@property (readonly, nonatomic, getter=isUpdating) BOOL updating;
// Returns nil if the owning MKMapView's showsUserLocation is NO or the user's location has
yet to be determined.
@property (readonly, retain, nonatomic) CLLocation *location;
// Returns nil if not in MKUserTrackingModeFollowWithHeading
@property (readonly, nonatomic, retain) CLHeading *heading NS_AVAILABLE(NA, 5_0);
// The title to be displayed for the user location annotation.
@property (nonatomic, copy) NSString *title;
// The subtitle to be displayed for the user location annotation.
@property (nonatomic, copy) NSString *subtitle;
@end
25. MKAnnotation
@protocol MKAnnotation <NSObject>
// Center latitude and longitude of the annotion view.
// The implementation of this property must be KVO compliant.
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@optional
// Title and subtitle for use by selection UI.
@property (nonatomic, readonly, copy) NSString *title;
@property (nonatomic, readonly, copy) NSString *subtitle;
// Called as a result of dragging an annotation view.
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate NS_AVAILABLE(NA, 4_0);
@end
26. MKAnnotation
• MKAnnotation 不是 delegate protocol
• 声明了⼀一套对于任何想要把⾃自⼰己的实例显⽰示到
map view 上的类⾮非常有⽤用的⽅方法
• ⽐比⽅方附近的酒店,⼯工⼚厂,⽕火⻋车站.... 这些类在应⽤用
程序中都是⾮非常不同并且层次⽆无关的,但是只要
他们满⾜足 MKAnnotation, 它们都可以被添加到
MKMapView
30. BNRMapPoint.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
@interface BNRMapPoint : NSObject <MKAnnotation>
{
}
-(id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t;
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@end
31. BNRMapPoint.m
@implementation BNRMapPoint
@synthesize coordinate, title;
- (id)init
{
return [self initWithCoordinate:CLLocationCoordinate2DMake(39.91503, 116.4631)
title:@"央视新台址"];
}
- (id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{
self = [super init];
if (self) {
coordinate = c;
[self setTitle:t];
}
return self;
}
@end
32. 给位置打标签
• 现在我们有了⼀一个符合 MKAnnotation 的类
(BNRMapPoint),我们可以把它的实例显⽰示在
地图上
• ⽤用户可以在 UITextField 中输⼊入位置的名称,然后
按下 keyboard 上的 Done 按钮
• 轻按 Done 是增加⼀一个 annotation 的信号,怎么
才能知道这个事件发⽣生了呢? 还是 Delegation
34. first responder
• UIResponder 是 UIKit framework 的⼀一个类,⼀一个
responder 负责接收和处理与其相关的事件
• UIView 是 UIResponder 的⼦子类,因此 UIView 对象
可以接收事件
• 按钮是可以处理触控事件的 responder,像 tap
• 晃动设备及点击键盘上的⼀一个键也会产⽣生事件
• responders 之⼀一就是 first responder, 同⼀一时间只能
有⼀一个 responder 可以作为 first responder
• first responder 处理那些不和屏幕上某⼀一具体位置
相关的事件。举例:tap 和 shaking的区别
35. resignFirstResponder
• UITextField 也是⼀一个 responder:它是 UIControl
的直接⼦子类,UIControl 是 UIView 的⼦子类,UIView
是 UIResponder 的⼦子类
• 当UITextField 被点击的时候,它通过变成 first
responder 来处理事件
• 当 UITextField 变成 first responder, ⼀一个键盘就会
⾃自动出现在屏幕上;要从屏幕上移除键盘,要通
过给它发送 resignFirstResponder 消息来告诉
UITextField 放弃它的 first responder 状态,⼀一旦
first responder 不再是 UITextField,键盘就会消失
37. <> 和 “”
• 和 C++ ⼀一样,从框架中包含的⽂文件使⽤用<>尖括
号,⾃自⼰己编写的头⽂文件使⽤用“”引号
• #import <MapKit/MapKit.h>,表⽰示仅在系统库下
⾯面查找这个⽂文件
• #import "BNRMapPoint.h",表⽰示⾸首先在项⺫⽬目⽂文件
下查找,找不到的话再在系统库下⾯面查找