在程序中集成地址簿、电子邮件和地图功能
地址簿
iOS通过两个框架提供了全面的地址簿数据库访问功能:Address Book和Address Book UI。
Address Book UI框架是一组用户界面类,封装了Address Book框架,并向用户提供了使用联系人信息的标准方式。通过使用Address Book UI框架的界面,用户可以在地址薄中浏览、搜索和选择联系人,显示并编辑选定联系人的信息,以及创建新的联系人。
要使用框架Address Book UI,需要将其加入到项目中,并导入其接口文件:
#import <AddressBook/AddressBook.h>
ABPeoplePickerNavigationController类提供一个显示地址薄UI的视图控制器,使用方法如下:
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init]; picker.peoplePickerDelegate = self; [self presentViewController:picker animated:YES completion:nil];
显示地址簿后,需要处理用户的选择;主要通过实现委托ABPeoplePickerNavigationControllerDelegate的三个方法:
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
第一个方法处理用户的取消操作。
第二个方法处理用户的第一次选择,在这个方法里可以获取用户的所有信息集合;当这个方法返回YES,将允许用户进一步选择。
第三个方法处理用户的第二次选择,在这个方法里可以获取用户选择的单项;当这个方法返回YES,将允许用户进一步选择。
在项目中使用地址簿示例:
#import <UIKit/UIKit.h> #import <AddressBook/AddressBook.h> #import <AddressBookUI/ABPeoplePickerNavigationController.h> @interface ViewController : UIViewController <ABPeoplePickerNavigationControllerDelegate> @end
#import "ViewController.h" @interface ViewController () - (IBAction)btnTestClickHandler:(id)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)btnTestClickHandler:(id)sender { ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init]; picker.peoplePickerDelegate = self; [self presentViewController:picker animated:YES completion:nil]; } //取消选择 - (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker { [self dismissViewControllerAnimated:YES completion:nil]; } //一次触发 - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { //first name NSString *strFirstName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); NSLog(@"first name: %@",strFirstName); //email ABMultiValueRef emailAddresses = ABRecordCopyValue(person, kABPersonEmailProperty); if(ABMultiValueGetCount(emailAddresses)>1) { NSString *strSecondEmail = (__bridge NSString *)ABMultiValueCopyValueAtIndex(emailAddresses, 1); NSLog(@"第二个Email: %@",strSecondEmail); } //phone number ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty); NSString *strPhone = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phoneNumbers, 0); NSLog(@"电话号码:%@",strPhone); return YES; } //二次触发 - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier { if(property == kABPersonPhoneProperty) { NSLog(@"你选择的是电话号码"); } ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, property); for(CFIndex i=0; i<ABMultiValueGetCount(phoneNumbers); i++) { if(identifier == ABMultiValueGetIdentifierAtIndex(phoneNumbers, i)) { NSString *strPhone = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phoneNumbers, i); NSLog(@"你选择的内容:%@",strPhone); } } return NO; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
电子邮件
在项目里使用框架Message UI可以很方便的发送电子邮件,只需要初始化一个MFMailComposeViewController对象来显示发邮件的界面就可以了,具体发送操作由iOS自动完成。
需要遵守一个协议:MFMailComposeViewControllerDelegate。该协议定义了一个清理方法:mailComposeController:didFinishWithResult:error,将在用户使用完邮件书写窗口后被调用。在大多数情况下,这个方法只需关闭邮件书写视图控制器即可。如果想进一步获悉邮件书写视图关闭的原因,可查看result(其类型为MFMailComposeResult)的值。其取值为下述常量之一:
MFMailComposeResultCancelled、MFMailComposeResultSaved、MFMailComposeResultSent和MFMailComposeResultFailed。
在项目中发送电子邮件示例:
#import <UIKit/UIKit.h> #import <MessageUI/MessageUI.h> @interface ViewController : UIViewController <UINavigationControllerDelegate, MFMailComposeViewControllerDelegate> @end
#import "ViewController.h" @interface ViewController () - (IBAction)btnTestClickHandler:(id)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)btnTestClickHandler:(id)sender { MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init]; NSArray *emailAddresses = [[NSArray alloc] initWithObjects:@"me@qq.com", nil]; mailComposer.delegate = self; [mailComposer setToRecipients:emailAddresses]; [self presentViewController:mailComposer animated:YES completion:nil]; } - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error { switch (result) { case MFMailComposeResultCancelled: NSLog(@"Mail cancelled"); break; case MFMailComposeResultSaved: NSLog(@"Mail saved"); break; case MFMailComposeResultSent: NSLog(@"Mail sent"); break; case MFMailComposeResultFailed: NSLog(@"Mail sent failure: %@", [error localizedDescription]); break; default: break; } // Close the Mail Interface [self dismissViewControllerAnimated:YES completion:nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
地图功能
通过使用iOS的Map Kit,可以将地图嵌入到视图中,并提供显示该地图所需的所有图块(图像)。它在需要时处理滚动、缩放和图块加载。Map Kit还能执行反向地理编码(reverse geocoding),即根据坐标获取位置信息(国家、州、城市、地址)。
无需编写任何代码就可使用Map Kit — 只需在Interface Builder将一个MKMapView实例加入到视图中,并可在Attributes Inspector中设置多个属性以进一步定制它。记得需要添加链接库MapKit.framework。
如果要以编程方式控制地图,首先需要导入框架Map Kit的接口文件:
#import <MapKit/MapKit.h>
需要操纵地图时,大多数情况下都需要添加框架Core Location并导入其接口文件:
#import <CoreLocation/CoreLocation.h>
还需要定义一个地图区域。区域(region)是一个MKCoordinateRegion结构(而不是对象),它包含成员center和span。
center — CLLocationCoordinate2D结构,包含成员longitude(经度)和latitude(纬度)。
span — 指定从中心出发向东西南北延伸多少度。一个纬度相当于69英里;在赤道上,一个经度也相当于69英里。通过将区域的跨度(span)设置为较小的值,如0.2,可将地图的覆盖范围缩小到绕重点几英里。
MKCoordinateRegion mapRegion; mapRegion.center.longitude = 90.0; mapRegion.center.latitude = 33.0; mapRegion.span.longitudeDelta = 0.2; mapRegion.span.latitudeDelta = 0.2; [self.myMap setRegion:mapRegion animated:YES];
在应用程序中可以给地图添加标注,通常需要实现一个MKAnnotaion View子类,它描述了标注的外观以及应显示的信息。
对于加入到地图中的每个标注,都需要一个描述其位置的地点标识对象(MKPlaceMark)。
//设置标记 CLLocationCoordinate2D myCoordinate; myCoordinate.longitude = 90.0; myCoordinate.latitude = 33.0; MKPlacemark *myMarker = [[MKPlacemark alloc] initWithCoordinate:myCoordinate addressDictionary:self.myAddress]; [self.myMap addAnnotation:myMarker]; //删除标记 //[self.myMap removeAnnotation:myMarker];
上面的代码的myAddress来自@property (nonatomic, readonly) NSDictionary *myAddress;这里只简单的声明了引用,实际应用中可能是从地址簿条目中获取的(通过邮编得到经纬度),也可能是根据ASPerson参考文档中Address属性的定义手工创建的。
添加标注时,iOS自动完成其他工作。Apple提供了一个MKAnnotationView子类—MKPinAnnotationView。当您添加标记时,iOS自动创建一个MKPinAnnotationView实例(一颗图钉),如果要定制图钉,必须实现地图视图的委托方法mapView:viewForAnnotation:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { MKPinAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"myspot"]; pin.animatesDrop = YES; //是否以动画方式出现 pin.canShowCallout = YES; //触摸时,是否能显示额外信息 pin.pinColor = MKPinAnnotationColorPurple; //图标颜色 return pin; }
需要设置MKMapView实例的delegate属性才能生效。