05 MapKit and Text Input
Upcoming SlideShare
Loading in...5
×
 

05 MapKit and Text Input

on

  • 668 views

MapKit 和文本输入

MapKit 和文本输入

Statistics

Views

Total Views
668
Views on SlideShare
668
Embed Views
0

Actions

Likes
0
Downloads
4
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

05 MapKit and Text Input 05 MapKit and Text Input Presentation Transcript

  • MapKit 和⽂文本输⼊入范圣刚,princetoad@gmail.com,www.tfan.org
  • • 在这⼀一章,我们将使⽤用 MapKit 框架,UITextField 类以及更多的 delegation 来完成 Whereami 应⽤用。• ⺫⽬目前,whereami 找到位置并且在控制台打印出 来。这章结束时,应⽤用程序将显⽰示出当前位置的 地图.并且⽤用户还有⼀一个可选项,可以使⽤用MapKit annotation 标记和命名当前的位置。默认的 MapKit annotation 显⽰示为地图上的⼀一个红⾊色的⼤大 头针。
  • 完成后的 Whereami
  • 对象⽰示意图(Object Diagrams)
  • view objects• MKAnnotationView • 在 MKMapView 上作为图标显⽰示的⼏几个 MKAnnotationView 的实例• MKMapView • 显⽰示地图,和所记录的位置的标签• UIActivityIndicatorView • 表⽰示当前设备还在⼯工作,没有⽌止步不前• UITextField • 允许⽤用户输⼊入⽂文本来给地图上的当前位置打标签
  • model objects• CLLocationManager • 和设备交互以确定⽤用户位置• BNRMapPoint • 我们⾃自⼰己创建的模型对象
  • controller object• WhereamiViewController • 负责处理来⾃自其他对象的更新和请求 • 是 MKMapView 的 delegate • 当⼀一个 view 或者多个 views 被添加上以后 MKMapView 会发 送 mapView:didAddAnnotationViews: • 是 UITextField 的 delegate • ⽤用户完成输⼊入⽂文本后,UITextField 会发送 textFieldShouldReturn: • 是 CLLocationManager 的 delegate • 发送 locationManager:didUpdateLocations: 通知 WhereamiViewController 位置已经更新
  • MapKit 框架• Core Location framework 告诉我们我们在世界上 的什么地⽅方• MapKit framework 把世界显⽰示给我们• MapKit 的主要⼯工作都是由 MKMapView 类完成的 • 显⽰示⼀一个地图 • 追踪触控 • 以及显⽰示注释(annotation)
  • 把 MapKit framework 加⼊入项⺫⽬目
  • 导⼊入 MapKit 头⽂文件#import <UIKit/UIKit.h>// 导⼊入 Core Location framework 的头⽂文件#import <CoreLocation/CoreLocation.h>// 导⼊入MapKit framework 的头⽂文件#import <MapKit/MapKit.h>
  • 声明必要的实例变量@interface WhereamiViewController : UIViewController<CLLocationManagerDelegate>{ CLLocationManager *locationManager; IBOutlet MKMapView *worldView; IBOutlet UIActivityIndicatorView *activityIndicator; IBOutlet UITextField *locationTitleField;}@end
  • 界⾯面属性(Interface Properties)1.从界⾯面右侧的 object library 中拖拽 MKMapView 到 UIView 上2.再拖拽 UITextField, UIActivityIndicatorView 到 MKMapView 上,适当调整位置和⼤大⼩小3.设置 ViewController 中实例变量到新增加的视图的 链接(IBOutlet指⽰示的)4.设置新增加的视图的 delegate 到 ViewController
  • XIB 布局
  • Finished connections
  • 调整 UITextField 属性• 设置 Placeholder• 设置 Return Key
  • 设置 UIActivityIndicator 属性• 不转的时候⾃自动隐藏• 勾选上“Hides When Stopped”
  • 作为 MapView 的 Delegate• 我们希望 Whereami 启动时,找到当前的位置并在 地图上显⽰示• 上⼀一个主题我们直接使⽤用 Core Location 查找⽤用户 的位置• MKMapView 实例本⾝身知道如何使⽤用 Core Location 查找⽤用户位置 • 设置 MKMapView 的 showUserLocation 属性为 YES, 然后它就会查找⽤用户的位置并把它显⽰示在地图上 • 界⾯面加载完以后,WhereamiViewController 会被发送 viewDidLoad 消息,我们在这⾥里⾯面告诉 MKMapView 来 更新它的位置。
  • 修改 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;}
  • MKMapViewDelegate• delegate 中是否有⼀一个⽤用户位置更新的事件?• 可以使⽤用⽂文档
  • ⽂文档• API Reference• System Guides• Tools Guides• Sample Code
  • mapView:didUpdateUserLocation• 通知⽤用户位置更新- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{}
  • 当前位置居中显⽰示并适当缩放• 已有数据:MKUserLocation• 需要调⽤用⽅方法:- (void)setRegion: (MKCoordinateRegion)region animated: (BOOL)animated
  • 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;
  • MKUserLocation@interface MKUserLocation : NSObject <MKAnnotation> { @private MKUserLocationInternal *_internal;}// Returns YES if the users location is being updated.@property (readonly, nonatomic, getter=isUpdating) BOOL updating;// Returns nil if the owning MKMapViews showsUserLocation is NO or the users location hasyet 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
  • 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
  • MKAnnotation• MKAnnotation 不是 delegate protocol• 声明了⼀一套对于任何想要把⾃自⼰己的实例显⽰示到 map view 上的类⾮非常有⽤用的⽅方法• ⽐比⽅方附近的酒店,⼯工⼚厂,⽕火⻋车站.... 这些类在应⽤用 程序中都是⾮非常不同并且层次⽆无关的,但是只要 他们满⾜足 MKAnnotation, 它们都可以被添加到 MKMapView
  • MKAnnotationView• 当⼀一个满⾜足 MKAnnotation 的对象被添加到 MKMapView 时,⼀一个MKAnnotationView 的实例 会被创建并添加到 map view• 这个 MKAnnotationView 持有⼀一个到这个对象的指 针,以便需要的时候可以向它请求数据
  • MKMapView 和 annotation
  • BNRMapPoint• 新建⼀一个类 BNRMapPoint, 让它遵守 MKAnnotation• 声明两个属性和⼀一个初始化器
  • 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
  • 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
  • 给位置打标签• 现在我们有了⼀一个符合 MKAnnotation 的类 (BNRMapPoint),我们可以把它的实例显⽰示在 地图上• ⽤用户可以在 UITextField 中输⼊入位置的名称,然后 按下 keyboard 上的 Done 按钮• 轻按 Done 是增加⼀一个 annotation 的信号,怎么 才能知道这个事件发⽣生了呢? 还是 Delegation
  • textFieldShouldReturn@interface WhereamiViewController : UIViewController<CLLocationManagerDelegate, MKMapViewDelegate,UITextFieldDelegate>- (BOOL)textFieldShouldReturn:(UITextField *)textField{ [self findLocation]; [textField resignFirstResponder]; return YES;}
  • first responder• UIResponder 是 UIKit framework 的⼀一个类,⼀一个 responder 负责接收和处理与其相关的事件• UIView 是 UIResponder 的⼦子类,因此 UIView 对象 可以接收事件• 按钮是可以处理触控事件的 responder,像 tap• 晃动设备及点击键盘上的⼀一个键也会产⽣生事件• responders 之⼀一就是 first responder, 同⼀一时间只能 有⼀一个 responder 可以作为 first responder• first responder 处理那些不和屏幕上某⼀一具体位置 相关的事件。举例:tap 和 shaking的区别
  • resignFirstResponder• UITextField 也是⼀一个 responder:它是 UIControl 的直接⼦子类,UIControl 是 UIView 的⼦子类,UIView 是 UIResponder 的⼦子类• 当UITextField 被点击的时候,它通过变成 first responder 来处理事件• 当 UITextField 变成 first responder, ⼀一个键盘就会 ⾃自动出现在屏幕上;要从屏幕上移除键盘,要通 过给它发送 resignFirstResponder 消息来告诉 UITextField 放弃它的 first responder 状态,⼀一旦 first responder 不再是 UITextField,键盘就会消失
  • 拼合使⽤用
  • <> 和 “”• 和 C++ ⼀一样,从框架中包含的⽂文件使⽤用<>尖括 号,⾃自⼰己编写的头⽂文件使⽤用“”引号• #import <MapKit/MapKit.h>,表⽰示仅在系统库下 ⾯面查找这个⽂文件• #import "BNRMapPoint.h",表⽰示⾸首先在项⺫⽬目⽂文件 下查找,找不到的话再在系统库下⾯面查找