05 mapkit and text input

37
MapKit 和本输 范圣刚,[email protected] www.tfan.org

Upload: tom-fan

Post on 10-May-2015

454 views

Category:

Technology


1 download

DESCRIPTION

MapKit 和文本输入

TRANSCRIPT

Page 2: 05 MapKit and Text Input

•在这⼀一章,我们将使⽤用 MapKit 框架,UITextField 类以及更多的 delegation 来完成 Whereami 应⽤用。

•⺫⽬目前,whereami 找到位置并且在控制台打印出来。这章结束时,应⽤用程序将显⽰示出当前位置的地图.并且⽤用户还有⼀一个可选项,可以使⽤用MapKit annotation 标记和命名当前的位置。默认的 MapKit annotation 显⽰示为地图上的⼀一个红⾊色的⼤大头针。

Page 3: 05 MapKit and Text Input

完成后的 Whereami

Page 4: 05 MapKit and Text Input

对象⽰示意图(Object Diagrams)

Page 5: 05 MapKit and Text Input

view objects

•MKAnnotationView

•在 MKMapView 上作为图标显⽰示的⼏几个 MKAnnotationView 的实例

•MKMapView

•显⽰示地图,和所记录的位置的标签•UIActivityIndicatorView

•表⽰示当前设备还在⼯工作,没有⽌止步不前•UITextField

•允许⽤用户输⼊入⽂文本来给地图上的当前位置打标签

Page 6: 05 MapKit and Text Input

model objects

• CLLocationManager

•和设备交互以确定⽤用户位置• BNRMapPoint

•我们⾃自⼰己创建的模型对象

Page 7: 05 MapKit and Text Input

controller object

•WhereamiViewController

•负责处理来⾃自其他对象的更新和请求•是 MKMapView 的 delegate

• 当⼀一个 view 或者多个 views 被添加上以后 MKMapView 会发送 mapView:didAddAnnotationViews:

•是 UITextField 的 delegate

• ⽤用户完成输⼊入⽂文本后,UITextField 会发送 textFieldShouldReturn:

•是 CLLocationManager 的 delegate

• 发送 locationManager:didUpdateLocations: 通知WhereamiViewController 位置已经更新

Page 8: 05 MapKit and Text Input

MapKit 框架• Core Location framework 告诉我们我们在世界上的什么地⽅方

•MapKit framework 把世界显⽰示给我们

•MapKit 的主要⼯工作都是由 MKMapView 类完成的•显⽰示⼀一个地图•追踪触控•以及显⽰示注释(annotation)

Page 9: 05 MapKit and Text Input

把 MapKit framework 加⼊入项⺫⽬目

Page 10: 05 MapKit and Text Input

导⼊入 MapKit 头⽂文件

#import <UIKit/UIKit.h>// 导⼊入 Core Location framework 的头⽂文件#import <CoreLocation/CoreLocation.h>// 导⼊入MapKit framework 的头⽂文件#import <MapKit/MapKit.h>

Page 11: 05 MapKit and Text Input

声明必要的实例变量

@interface WhereamiViewController : UIViewController <CLLocationManagerDelegate>{ CLLocationManager *locationManager; IBOutlet MKMapView *worldView; IBOutlet UIActivityIndicatorView *activityIndicator; IBOutlet UITextField *locationTitleField;}@end

Page 12: 05 MapKit and Text Input

界⾯面属性(Interface Properties)1.从界⾯面右侧的 object library 中拖拽 MKMapView 到

UIView 上2.再拖拽 UITextField, UIActivityIndicatorView 到

MKMapView 上,适当调整位置和⼤大⼩小3.设置 ViewController 中实例变量到新增加的视图的链接(IBOutlet指⽰示的)

4.设置新增加的视图的 delegate 到 ViewController

Page 13: 05 MapKit and Text Input

XIB 布局

Page 14: 05 MapKit and Text Input

Finished connections

Page 15: 05 MapKit and Text Input

调整 UITextField 属性•设置 Placeholder

•设置 Return Key

Page 16: 05 MapKit and Text Input

设置 UIActivityIndicator 属性•不转的时候⾃自动隐藏•勾选上“Hides When

Stopped”

Page 17: 05 MapKit and Text Input

作为 MapView 的 Delegate

•我们希望 Whereami 启动时,找到当前的位置并在地图上显⽰示

•上⼀一个主题我们直接使⽤用 Core Location 查找⽤用户的位置

•MKMapView 实例本⾝身知道如何使⽤用 Core Location 查找⽤用户位置•设置 MKMapView 的 showUserLocation 属性为 YES,然后它就会查找⽤用户的位置并把它显⽰示在地图上

•界⾯面加载完以后,WhereamiViewController 会被发送 viewDidLoad 消息,我们在这⾥里⾯面告诉 MKMapView 来更新它的位置。

Page 18: 05 MapKit and Text Input

修改 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;}

Page 19: 05 MapKit and Text Input

MKMapViewDelegate

• delegate 中是否有⼀一个⽤用户位置更新的事件?

•可以使⽤用⽂文档

Page 20: 05 MapKit and Text Input

⽂文档• API Reference

• System Guides

• Tools Guides

• Sample Code

Page 21: 05 MapKit and Text Input

mapView:didUpdateUserLocation

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{}

•通知⽤用户位置更新

Page 22: 05 MapKit and Text Input

当前位置居中显⽰示并适当缩放•已有数据:MKUserLocation

•需要调⽤用⽅方法:- (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated

Page 23: 05 MapKit and Text Input

MKCoordinateRegiontypedef struct {! CLLocationCoordinate2D center;! MKCoordinateSpan span;} MKCoordinateRegion;

typedef struct {! CLLocationDegrees latitude;! CLLocationDegrees longitude;} CLLocationCoordinate2D;

typedef double CLLocationDegrees;

typedef struct { CLLocationDegrees latitudeDelta; CLLocationDegrees longitudeDelta;} MKCoordinateSpan;

Page 24: 05 MapKit and Text Input

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

Page 25: 05 MapKit and Text Input

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

Page 26: 05 MapKit and Text Input

MKAnnotation

•MKAnnotation 不是 delegate protocol

•声明了⼀一套对于任何想要把⾃自⼰己的实例显⽰示到 map view 上的类⾮非常有⽤用的⽅方法

•⽐比⽅方附近的酒店,⼯工⼚厂,⽕火⻋车站.... 这些类在应⽤用程序中都是⾮非常不同并且层次⽆无关的,但是只要他们满⾜足 MKAnnotation, 它们都可以被添加到 MKMapView

Page 27: 05 MapKit and Text Input

MKAnnotationView

•当⼀一个满⾜足 MKAnnotation 的对象被添加到 MKMapView 时,⼀一个MKAnnotationView 的实例会被创建并添加到 map view

•这个 MKAnnotationView 持有⼀一个到这个对象的指针,以便需要的时候可以向它请求数据

Page 28: 05 MapKit and Text Input

MKMapView 和 annotation

Page 29: 05 MapKit and Text Input

BNRMapPoint

•新建⼀一个类 BNRMapPoint, 让它遵守 MKAnnotation

•声明两个属性和⼀一个初始化器

Page 30: 05 MapKit and Text Input

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

Page 31: 05 MapKit and Text Input

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

Page 32: 05 MapKit and Text Input

给位置打标签•现在我们有了⼀一个符合 MKAnnotation 的类(BNRMapPoint),我们可以把它的实例显⽰示在地图上

•⽤用户可以在 UITextField 中输⼊入位置的名称,然后按下 keyboard 上的 Done 按钮

•轻按 Done 是增加⼀一个 annotation 的信号,怎么才能知道这个事件发⽣生了呢? 还是 Delegation

Page 33: 05 MapKit and Text Input

textFieldShouldReturn@interface WhereamiViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate>

- (BOOL)textFieldShouldReturn:(UITextField *)textField{ [self findLocation]; [textField resignFirstResponder]; return YES;}

Page 34: 05 MapKit and Text Input

!rst responder

•UIResponder 是 UIKit framework 的⼀一个类,⼀一个 responder 负责接收和处理与其相关的事件

•UIView 是 UIResponder 的⼦子类,因此 UIView 对象可以接收事件

•按钮是可以处理触控事件的 responder,像 tap

•晃动设备及点击键盘上的⼀一个键也会产⽣生事件• responders 之⼀一就是 !rst responder, 同⼀一时间只能有⼀一个 responder 可以作为 !rst responder

• !rst responder 处理那些不和屏幕上某⼀一具体位置相关的事件。举例:tap 和 shaking的区别

Page 35: 05 MapKit and Text Input

resignFirstResponder

•UITextField 也是⼀一个 responder:它是 UIControl 的直接⼦子类,UIControl 是 UIView 的⼦子类,UIView 是 UIResponder 的⼦子类

•当UITextField 被点击的时候,它通过变成 !rst responder 来处理事件

•当 UITextField 变成 !rst responder, ⼀一个键盘就会⾃自动出现在屏幕上;要从屏幕上移除键盘,要通过给它发送 resignFirstResponder 消息来告诉 UITextField 放弃它的 !rst responder 状态,⼀一旦 !rst responder 不再是 UITextField,键盘就会消失

Page 36: 05 MapKit and Text Input

拼合使⽤用

Page 37: 05 MapKit and Text Input

<> 和 “”

•和 C++ ⼀一样,从框架中包含的⽂文件使⽤用<>尖括号,⾃自⼰己编写的头⽂文件使⽤用“”引号

• #import <MapKit/MapKit.h>,表⽰示仅在系统库下⾯面查找这个⽂文件

• #import "BNRMapPoint.h",表⽰示⾸首先在项⺫⽬目⽂文件下查找,找不到的话再在系统库下⾯面查找