前言 常见的那些功能,其实经常用不到,但是用到的时候又是经常用的到,总结一下,以免一时脑子瓦特想不起来
随着API的更新,打电话的方式也在改变
- (void)callType01 {
NSURL *url = [NSURL URLWithString:@"tel://10086"];
if ([[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"tel://"]]) {
BOOL result = [[UIApplication sharedApplication]openURL:url];
NSLog(@"%d",result);
}
}
简述:该api在iOS10.0被弃用
iOS9.0以前,打电话前没有弹窗提示、通话结束后不能返回到app;
在iOS10.2以前,打电话前没有弹窗提示;
在10.2.1开始,有弹窗提示。
返回指是一个BOOL类型,通过返回值来判断呼叫状态
- (void)callType02 {
NSURL *url = [NSURL URLWithString:@"tel://10086"];
if ([[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"tel://"]]) {
[[UIApplication sharedApplication]openURL:url options:@{} completionHandler:nil];
}
}
简述:iOS10.0之后的新API
iOS10.2之前,没有弹窗提示,之后有弹窗提示,结束之后能返回到当前app
completionHandler返回值能获得呼叫状态
在旧的API中,部分版本没吊起电话前没有弹窗提示,这会引起误操作呼叫电话,造成不必要的麻烦,所以会使用
NSURL *url =[NSURL URLWithString:@“telprompt://10000”];
把@“tel://” 修改成@“telprompt://”,这样在呼叫之前就会有弹窗提示;但是从后续的API发展看,apple似乎也注意到了直接呼出没有弹窗提示的弊端,这不符合苹果的安全意识逻辑,后续的系统版本陆续加上弹窗提示,所以再没必要这么使用了,而且这么使用可能会引起上架审核失败,所以仅限于了解便可
- (void)callType03 {
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectZero];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"tel://10010"]]];
[self.view addSubview:webView];
}
简述 :版本的分界线已经不清楚了,用的12的版本测试在呼叫之前是有弹窗提示的,在iOS 13之后,官方建议别再使用UIWebView,所以新的项目还是尽量去使用WKWebView去处理
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURL *url = navigationAction.request.URL;
NSString *scheme = [url scheme];
UIApplication *app = [UIApplication sharedApplication];
// 打电话
if ([scheme isEqualToString:@"tel"]) {
if ([app canOpenURL:url]) {
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
} else {
[[UIApplication sharedApplication] openURL:url];
}
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
}
简述 : 在- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction;方法中去实现
if ([[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"SMS://"]] ) {
NSURL *url = [NSURL URLWithString:@"sms://10000"];
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
} else {
[[UIApplication sharedApplication] openURL:url];
}
}
直接唤起短信页面,不预设置短信内容,短信发送完成或者取消发送后留在短信页面,不返回当前app
NSString *phoneStr = [NSString stringWithFormat:@"10010"];//发短信的号码
NSString *smsContentStr = [NSString stringWithFormat:@"喵,我不想你只是情不自已的想给你发个短信。汪"];
NSString *urlStr = [NSString stringWithFormat:@"sms://%@&body=%@", phoneStr, smsContentStr];
// 需要处理中文
urlStr = [urlStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url = [NSURL URLWithString:urlStr];
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
} else {
[[UIApplication sharedApplication] openURL:url];
}
直接唤起短信页面,预设置短信内容,短信发送完成或者取消发送后留在短信页面,不返回当前app
目前测试,该方式发送短信只识别第一个号码;如果传入一组号码,以","分割,依然是只识别第一个号码,并小概率引起短息编辑页面bug,取消编辑按钮失效,编辑页面无法退出。所以群发还没处理方式,或者说我个人还没找到这种方法下的群发操作。
同时遵守协议,设置代理,协议方法中可以监听短信的发送状态(枚举)MessageComposeResult
- (void)SMS02 {
// 判断短信功能是否可用
if (![MFMessageComposeViewController canSendText]) {
NSLog(@"小主!您的设备不能发送短信~");
return;
}
MFMessageComposeViewController * controller = [[MFMessageComposeViewController alloc] init];
// 数组的形式加入多个号码
controller.recipients = @[@"10010", @"10000"];
// 预设置短信内容
controller.body = @"汪,下午三点的月亮真的好漂亮。喵";
controller.messageComposeDelegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
#pragma mark - MFMessageComposeViewControllerDelegate
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result{
[self dismissViewControllerAnimated:YES completion:nil];
switch (result) {
case MessageComposeResultSent:
NSLog(@"发送成功");
break;
case MessageComposeResultFailed:
NSLog(@"发送失败");
break;
case MessageComposeResultCancelled:
NSLog(@"取消发送");
break;
default:
break;
}
}
直接唤起短信页面,预设置短信内容,短信发送完成或者取消发送后返回当前app,能够群发短信
附:前面也介绍了openURL和openURL: options: completionHandler: 的区别,当今版本,已经到iOS 13以上了,微信都不兼容太低的系统版本,加上写个人写的demo是从iOS11开始,故之后的demo对部分兼容低版本的不在体现在代码中。
if (![[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"mailto://"]]) {
NSLog(@"小主!您的设备不能发送邮件~");
return;
}
NSURL *url = [NSURL URLWithString:@"mailto:[email protected]"];
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
直接唤起邮箱页面,不预设置邮件内容,邮件发送完成或者取消发送后留在邮箱,不返回当前app
NSMutableString *mailUrl = [[NSMutableString alloc]init];
// 添加收件人
NSArray *toRecipients = [NSArray arrayWithObjects:@"[email protected]", @"[email protected]", nil];
[mailUrl appendFormat:@"mailto:%@", [toRecipients componentsJoinedByString:@","]];
// 添加抄送对象
NSArray *ccRecipients = [NSArray arrayWithObjects:@"[email protected]", nil];
[mailUrl appendFormat:@"?cc=%@", [ccRecipients componentsJoinedByString:@","]];
// 添加密对象
NSArray *bccRecipients = [NSArray arrayWithObjects:@"[email protected]", nil];
[mailUrl appendFormat:@"&bcc=%@", [bccRecipients componentsJoinedByString:@","]];
// 设置主题
[mailUrl appendString:@"&subject=致喵和汪"];
// 设置邮件内容
[mailUrl appendString:@"&body=请别再见面就打架了,谢谢 \n--局外人!"];
NSString* email = [mailUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
// 发送
[[UIApplication sharedApplication] openURL: [NSURL URLWithString:email] options:@{} completionHandler:nil];
直接唤起邮箱页面,预设置邮件内容,邮件发送完成或者取消发送后留在邮箱,不返回当前app
- (void)email02 {
if (![MFMailComposeViewController canSendMail]) {
NSLog(@"小主!您的设备不能发送邮件~");
return;
}
MFMailComposeViewController *mailCompose = [[MFMailComposeViewController alloc] init];
mailCompose.mailComposeDelegate = self;
// 设置主题
[mailCompose setSubject: @"致喵和汪"];
// 添加收件人
NSArray *toRecipients = [NSArray arrayWithObjects:@"[email protected]", @"[email protected]", nil];
[mailCompose setToRecipients: toRecipients];
// 添加抄送对象
NSArray *ccRecipients = [NSArray arrayWithObjects:@"[email protected]", @"[email protected]", nil];
[mailCompose setCcRecipients:ccRecipients];
// 添加密对象
NSArray *bccRecipients = [NSArray arrayWithObjects:@"[email protected]", nil];
[mailCompose setBccRecipients:bccRecipients];
// 邮件添加图片内容
UIImage *addPic = [UIImage imageNamed: @"protait"];
NSData *imageData = UIImagePNGRepresentation(addPic);
// mineType 设置不同的附件内容 如图片、pdf文件、视频等 :https://www.iana.org/assignments/media-types/media-types.xhtml
[mailCompose addAttachmentData:imageData mimeType:@"image" fileName:@"pic.png"];
// 设置邮件主题:isHTML-> YES:富文本 NO:字符串
NSString *emailBody = @"喵、汪~ \n请别再见面就打架了,谢谢 \n--局外人!";
[mailCompose setMessageBody:emailBody isHTML:YES];
[self presentViewController:mailCompose animated:NO completion:nil];
}
#pragma mark - MFMailComposeViewControllerDelegate
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
[controller dismissViewControllerAnimated:YES completion:nil];
switch (result) {
case MFMailComposeResultCancelled:
NSLog(@"取消编辑");
break;
case MFMailComposeResultSaved:
NSLog(@"保存邮件");
break;
case MFMailComposeResultSent:
NSLog(@"用户已发送,邮件进入发送队列");
break;
case MFMailComposeResultFailed:
NSLog(@"保存/发送失败");
break;
default:
break;
}
}
直接唤起邮件页面,预设置邮件内容,邮件发送完成或者取消发送后返回当前app,能够群发邮件
iOS 9之前的旧框架AddressBookUI和AddressBook就不在这谈及了,谈谈iOS 9之后的新框架ContactsUI和Contacts
#import
- (void)conctact01 {
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusNotDetermined) {
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError* _Nullable error) {
if (error) {
NSLog(@"你没有获取用户联系人列表权限");
} else {
[self infoLost];
}
}];
} else if(status == CNAuthorizationStatusRestricted) {
NSLog(@"你没有获取用户联系人列表权限");
} else if (status == CNAuthorizationStatusDenied) {
NSLog(@"你没有获取用户联系人列表权限");
} else if (status == CNAuthorizationStatusAuthorized) {
[self infoLost];
}
}
/// 所有电话号码 无情丢失
- (void)infoLost {
NSArray *keysToFetch = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
CNContactFetchRequest *fetchRequest = [[CNContactFetchRequest alloc] initWithKeysToFetch:keysToFetch];
CNContactStore *contactStore = [[CNContactStore alloc] init];
[contactStore enumerateContactsWithFetchRequest:fetchRequest error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
// 姓名
NSString * familyName = contact.familyName;
NSString * givenName = contact.givenName;
// 电话
NSArray * phoneNums = contact.phoneNumbers;
CNLabeledValue *labelValue = phoneNums.firstObject; // 选取第一个电话
NSString *phoneValue = [labelValue.value stringValue];
NSLog(@"姓名:%@%@ 电话:%@", familyName, givenName, phoneValue);
}];
}
该方式只提供联系人信息,没有UI界面,想要界面可以自己搭建,或者用ContactUI的方式,在使用之前申请使用通讯录权限。
附:骚一句
我以为那些在我手机里的是我的秘密,没想到它只是皇帝的新装
- (void)conctact02 {
_contactPickerViewController = [[CNContactPickerViewController alloc]init];
_contactPickerViewController.delegate = self;
[self presentViewController:_contactPickerViewController animated:YES completion:nil];
}
#pragma mark - CNContactPickerDelegate
/// 取消事件
- (void)contactPickerDidCancel:(CNContactPickerViewController *)picker {
NSLog(@"contactPickerDidCancel - %@", picker);
}
/// 从通讯录直接获取联系人
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact {
// 姓名
NSString * familyName = contact.familyName;
NSString * givenName = contact.givenName;
// 电话
NSArray * phoneNums = contact.phoneNumbers;
CNLabeledValue *labelValue = phoneNums.firstObject; // 选取第一个电话
NSString *phoneValue = [labelValue.value stringValue];
NSLog(@"姓名:%@%@ 电话:%@", familyName, givenName, phoneValue);
}
/// 到联系人主页获取联系人
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty {
// 姓名
NSString * familyName = contactProperty.contact.familyName;
NSString * givenName = contactProperty.contact.givenName;
// 电话
NSString * phoneNum = [contactProperty.value stringValue];
NSLog(@"姓名:%@%@ 电话:%@ -- %@", familyName, givenName, phoneNum, contactProperty.contact.phoneNumbers);
}
/// 在通讯录同时选取多个联系人,点击完成按钮,获得多个联系人信息
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContacts:(NSArray<CNContact*> *)contacts {
for (CNContact * contact in contacts) {
// 姓名
NSString * familyName = contact.familyName;
NSString * givenName = contact.givenName;
// 电话
NSArray * phoneNums = contact.phoneNumbers;
CNLabeledValue *labelValue = phoneNums.firstObject; // 选取第一个电话
NSString *phoneValue = [labelValue.value stringValue];
NSLog(@"姓名:%@%@ 电话:%@", familyName, givenName, phoneValue);
}
}
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperties:(NSArray<CNContactProperty*> *)contactProperties {
}
需要设置代理CNContactPickerDelegate,在代理的几个方法中需要,获取联系人信息的四个方法需要单独使用,根据需求去选择,因为不同的代理方法,在通讯录页面的展示和选择方式不一样