高新技术:短信 & 邮件 & 拨打电话 & 验证码 & 程序跳转 & 静态库 & 通知 & 上架

真机测试录制屏幕
OSX QuickTime Player -> 文件 ->屏幕录制

*iOS 9.0开放免费真机测试 *

OS X-code步骤:
1. AppID:注册iCloud
2. 设备
3. 添加AppID到Xcode
4. 连接手机到mac上
5. Target - General - Team(Fix Issue)
6. Target - Build Settings - 搜索(code signing ->Debug 修改)
7. 选择设备
8. 运行程序

手机:
设置 - 通用 - 设备管理(描述文件)

1. 短信

方式一 功能少-> 不能指定发短信的那内容 不能回到原来的应用

- (IBAction)sendMessage:(UIButton *)sender {
  NSURL *url = [NSURL URLWithString:@"sms://xxx xxxx xxxx"];
  [[UIApplication sharedApplication]openURL:url];
}

方式二 功能多 -> 指定内容 多个发送对象 返回

头文件   #import <MessageUI/MessageUI.h>
遵守协议 <MFMessageComposeViewControllerDelegate> 

-> 点击触发:

- (IBAction)sendMessage:(UIButton *)sender {
    [self showMessageView:@[@"xxx xxxx xxxx"] title:@"msg title" body:@"测试发短信"];
   
}

-> 调用方法

-(void)showMessageView:(NSArray *)phones title:(NSString *)title body:(NSString *)body{
    if ([MFMessageComposeViewController canSendText]) {
        MFMessageComposeViewController *msgController = [MFMessageComposeViewController new];
        //设置接收人 内容 标题
        msgController.recipients = phones;
        msgController.body = body;
        msgController.title = title;
        //设置代理*********代理
        msgController.messageComposeDelegate = self;
        msgController.navigationBar.tintColor = [UIColor redColor];
        [self presentViewController:msgController animated:YES completion:nil];
    }else{
        NSLog(@"该设备不能发短信");
    }
}

-> 实现协议* #pragma mark - MFMessageComposeViewControllerDelegate*

-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result{
    switch (result) {
        case MessageComposeResultSent:
            NSLog(@"发送成功");
            break;
        case MessageComposeResultFailed:
            NSLog(@"发送失败");
        case MessageComposeResultCancelled:
            NSLog(@"取消发送");
        default:
            break;
    }
}

2. 邮件

几乎和发短信相同 要在icloud中打开邮件并设置账号

头文件   #import <MessageUI/MessageUI.h>
遵守协议 <MFMailComposeViewControllerDelegate> 

->点击触发

** 发邮件*
- (IBAction)sendMail:(UIButton *)sender {
    if ([MFMailComposeViewController canSendMail]) {
        MFMailComposeViewController *mailCon = [MFMailComposeViewController new];
        [mailCon setSubject:@"我的周报"];
        [mailCon setToRecipients:@[@"guoaj@tedu.cn"]];
        
        /** 抄送*/
        // [mailCon setCcRecipients:<#(nullable NSArray<NSString *> *)#>];
        /** 密送*/
        // [mailCon setBccRecipients:<#(nullable NSArray<NSString *> *)#>];
        
        [mailCon setMessageBody:@"这是我的周报<font color = \"red\" size = 6>周报的内容:今天是周三 </font> 请查阅" isHTML:YES];/* ----> no 直接发文本*/
        /** 附件*/
        UIImage *image = [UIImage imageNamed:@"pic"];
        NSData *imageData = UIImagePNGRepresentation(image);
        [mailCon addAttachmentData:imageData mimeType:@"image/png" fileName:@"abc.png"];
        
        //设置代理
        mailCon.mailComposeDelegate = self;
               
        [self presentViewController:mailCon animated:YES completion:nil];
    }else{
        NSLog(@"不能发邮件");
    }
}

-> 实现协议*# pragma mark - MFMailComposeViewControllerDelegate *


-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result{
    switch (result) {
        case MessageComposeResultSent:
            NSLog(@"发送成功");
            break;
        case MessageComposeResultFailed:
            NSLog(@"发送失败");
        case MessageComposeResultCancelled:
            NSLog(@"取消发送");
        default:
            break;
    }
    [self dismissViewControllerAnimated:YES completion:nil];
}

3. 打电话

方式一:直接拨出

 NSURL *url = [NSURL URLWithString:@"tel://xxx xxxx xxxx"];
 [[UIApplication sharedApplication]openURL:url];

方式二:会给用户一个选择,用于黑苹果设备,但这种方式上线可能遭到拒绝

 NSURL *url = [NSURL URLWithString:@"telprompt://xxx xxxx xxxx"];
 [[UIApplication sharedApplication]openURL:url];

方式三:有选择机会

@interface ViewController ()
{
    UIWebView *_webView;
}

@implementation ViewController
 if (_webView == nil) {
        _webView = [[UIWebView alloc]initWithFrame:CGRectZero];
    } 
    NSURL *url = [NSURL URLWithString:@"tel://xxx xxxx xxxx"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];     
 [_webView loadRequest:request];

4. 短信验证码@网址

  • 1 mob.com注册账号,激活
  • 2 登录账号
    鼠标放在右上角的头像 -> 出现进入后台
  • 3 找到对应的模块 新建应用
    获取appkey和appsecret
  • 4 按照官方文档 实现短信验证
#import "AppDelegate.h"
#import <SMS_SDK/SMSSDK.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [SMSSDK registerApp:MOBAPPKEY withSecret:MOBAPPSECRECT];
    return YES;
}
 #import "ViewController.h"
 #import <SMS_SDK/SMSSDK.h>
 
**获取验证码**
- (IBAction)getMsgCode:(UIButton *)sender {
    [SMSSDK getVerificationCodeByMethod:SMSGetCodeMethodSMS phoneNumber:@"xxxxxx" zone:@"86" customIdentifier:nil result:^(NSError *error) {
        if (error) {
            NSLog(@"获取验证码失败,%@",error);
        }else{
            NSLog(@"获取验证码失败");
        }
    }];
}

**验证**
- (IBAction)validMsgCode:(UIButton *)sender {
    [SMSSDK commitVerificationCode:self.msgCodeField.text phoneNumber:@"xxxxxx" zone:@"86" result:^(NSError *error) {
        if (error) {
            NSLog(@"验证失败");
        }else
        {
            NSLog(@"验证成功");
        }
    }];
}

5. 应用程序间跳转

  • 1 建立一个程序叫MyApp 建立另一个应用程序叫YourApp
  • 2 在YourApp增加标识 Target -> Info -> URL Types ->增加 ->URLSchemes (YourApp)
  • 3在MyAPP设置白名单(IOS9之后的要求)Target -> Info -> LSApplicationQueriesSchemes(Array) ->增加(YourApp)
NSURL *url = [NSURL URLWithString:@"YourApp://"];
   UIApplication *app = [UIApplication sharedApplication];
   if ([app canOpenURL:url]) {
       [app openURL:url];
   }else{
       NSLog(@"打开应用程序失败");
   }

跳转到其他应用,例如:微博、微信等...找到相应地scheme和设置白名单

NSURL *url = [NSURL URLWithString:@"sinaweibo://"];
    UIApplication *app = [UIApplication sharedApplication];
    if ([app canOpenURL:url]) {
        [app openURL:url];
    }else{
        NSLog(@"无法跳转到微博");
    }

进阶:拦截参数 -> 从MyApp跳转到YourApp 二级页面- Page2

  • MyApp配置
- (IBAction)gotoYourApp:(UIButton *)sender {
    NSURL *url = [NSURL URLWithString:@"YourApp://aaa?backScheme=MyApp"];
    UIApplication *app = [UIApplication sharedApplication];
    if ([app canOpenURL:url]) {
        [app openURL:url];
    }else{
        NSLog(@"打开应用程序失败");
    }
}

- (IBAction)gotoYourAppP2:(UIButton *)sender {
    NSURL *url = [NSURL URLWithString:@"YourApp://bbb?backScheme=MyApp"];
    UIApplication *app = [UIApplication sharedApplication];
    if ([app canOpenURL:url]) {
        [app openURL:url];
    }else{
        NSLog(@"打开应用程序P2失败");
    }
}
  • YourApp配置
 #import Appdelegate

-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
    ***获取
    NSLog(@"%@",url.absoluteString);

    ***获取导航控制
    UINavigationController *navi = (UINavigationController *)self.window.rootViewController;
    ViewController *mainVc = (ViewController *)navi.topViewController;
    NSString *urlString = url.absoluteString;
    NSRange range = [urlString rangeOfString:@"backScheme="];
    
    if (range.length > 0) {
        NSInteger fromInteger = range.location + range.length;
        NSString *backStr = [urlString substringFromIndex:fromInteger];
        mainVc.backScheme = backStr;
        NSLog(@"backStr:%@",backStr);/*****打印结果:`MyApp`
    }
    
    ***开始跳转到P2
    if ([urlString hasPrefix:@"YourApp://bbb"]) {
        [mainVc performSegueWithIdentifier:@"page2Segie" sender:nil];
    }
    return YES;
}

```
```
#import "ViewController.h"
- (IBAction)gotoMyApp:(UIButton *)sender {
//    NSURL *url = [NSURL URLWithString:@"MyApp://"];
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@://",self.backScheme]];
    UIApplication *app = [UIApplication sharedApplication];
    if ([app canOpenURL:url]) {
        [app openURL:url];
    }else{
        NSLog(@"打开应用程序失败");
    }
}
```

>以下为APP跳转的三种方法

**方法一:已经抛弃**

```
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
```

**方法二:ios9刚过时 目前使用(为了防止IOS版本不足)**

```
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
    NSLog(@"%@",url.absoluteString);
    return YES;
}
```

**方法三:ios9之后出现**

```
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
    
}
```

# 6. 静态库
>概念:在我们的应用中由一些共用的代码,需要反复使用,并且希望隐藏代码具体的实现就可以把这部分代码做成静态库.如果不提供源代码叫闭源库,如果提供的是源代码叫开源库

- 1 如何制作静态库?
```
    framework(可能是静态 也可能是动态) - (增加头文件:Target -> BuildPhases ->CopyFiles)
```
- 2 如何使用静态库
    1. 真机使用真机库  2. 模拟器使用模拟器库

终端合成两个文件
 ```
lipo -create/路径/Debug-iphoneos/libStaticLibrary.a /路径/Debug-iphonesimulator/libStaticLibrary.a -output/目标地址/libStaticLibraryFile.a
```
合成完成了,就可以使用了。把.h文件和合成的.a文件放入你的工程中。

# 7. 推送
>概述:不在前台的应用通知,如果程序内部发生了一些用户感兴趣的,推送通知可以告知用户发生了哪些事情。通知是一种消息机制。分为本地推送和远程推送通知。

四种形式:APP激活状态(前台or后台)     APP彻底关闭(通知进入or图标进入)

#####推送通知的表现形式
- 1 顶部横幅 
- 2 中间提醒 (`其中顶部视图和中间视图只能二选一`)
- 3 锁屏提示
- 4 图标数字
- 5 通知中心(从上向下滑动屏幕)

#####特点
-  APP关闭时,可以接收并显示通知
-  APP打开,并处于后台.可以接收并显示通知
-  APP打开并处于前台,不会接收通知且不会显示通知
-  点击通知后,默认会自动打开发出通知的APP

##1. 本地通知
  >概述:不需要连接互联网,就可以发出的通知,不需要服务器的支持。本地通知是本地应用程序发出的,它是基于时间行为的一种通知。例如:闹钟定时、待办事项提醒、内存清理提醒

`注意`:iOS8.0 以后需要申请用户同意
```
获取用户设备系统版本:[UIDevice currentDevice].systemVersion.floatValue
```

**本地通知使用步骤:**

1. 创建一个本地通知UILocalNotification
```
#import "AppDelegate.h"
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil];
        [[UIApplication sharedApplication]registerUserNotificationSettings:settings];
```
2. 设置本地通知(启动时间 内容 主题 声音 图标数字)
3. 配置自定义的参数userInfo(`非必须`)
4. 调度通知(scheduleLocalNotification计划执行 or 马上执行)

_本地通知属性介绍:_

```
触发时间  @property(nullable, nonatomic,copy) NSDate *fireDate;  
显示内容  @property(nullable, nonatomic,copy) NSString *alertBody;
通知标题  @property(nullable, nonatomic,copy) NSString *alertTitle;
声音提示  @property(nullable, nonatomic,copy) NSString *soundName;
图标数字  @property(nullable, nonatomic,assign) NSInteger applicationIconBadgeNumber;
锁屏时    @property(nullable, nonatomic,copy) NSString *alertAction;
通知间隔  @property(nullable, nonatomic,assign) NSCalendarUnit  *repeatCanlendar;
点击通知显示图片 @property(nullable, nonatomic,copy) NSString *alertLaunchImage;
传参数    @property(nullable, nonatomic,copy) NSDictionary *userInfo;  ->userInfo[@"username"] = @"xxx"  -> localNoti.userInfo = userInfo;;
```

###本地通知的接收
##### App没有彻底关闭的时候(在前台或者后台),执行以下方法

```
#import "AppDelegate.h"
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
    **判断APP是否处于前台**
    if (application.applicationState == UIApplicationStateActive) {
        NSLog(@"通知来了");
    }else{
        NSLog(@"进入查看");
        NSLog(@"接收到本地通知");
        NSLog(@"%@",notification.userInfo[@"username"]);
    }
}
```
#####App彻底关闭,执行以下方法
**判断程序是通过点击图片进入 还是 通过点击通知进入**
- launchOptions 非空  证明是点击通知进入的
     ->通过key:UIApplicationLaunchOptionsLocalNoticifationKey取得通知对象
- launchOptions 是空 则使用点击图标进入的

```
#import "AppDelegate.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    if (launchOptions) {
        label.text = [NSString stringWithFormat:@"点击通知进入:%@",launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]];
     }else
         {
  label.text = @"图标启动 进入主界面";
         }
}
```

**取消通知**

```
取消某个通知 [[UIApplication sharedApplication]cancelLocalNotification:<#(nonnull UILocalNotification *)#>];
全部通知移除 [[UIApplication sharedApplication]cancelAllLocalNotifications];
```

##2. 远程通知
>需要联网并且需要服务器的支持,在联网状态下,所有的Apple设备都会和Apple的服务器保持长连接。
长连接的作用:时间校准、系统升级、查找我的iphone、传输速度快

1. APNS(Apple Push Notification Service)流程
 - 1  -App 向IOS注册远程推送请求,iOS就会发送请求到APNS服务器
 - 2  -APNS 返回device_token (设备标识+App标识),最终交给App
 - 3  -App 将device_token交给 企业的PUSH服务器程序
 - 4  -当企业服务器认为需要推送某些消息时,就会发请求到APNS
 - 5  -APNS根据企业PUSH服务器的请求推送通知到对应的App

2. 申请证书[Apple开发者中心](https://developer.apple.com)
创建证书过程中需要CSR(Certificate Signing Request)文件
       准备:创建CSR文件: LaunchPad - 其他 - 钥匙串 - 我的证书 - 证书助理 - 从证书颁发机构请求证书
例子@[1](http://www.jianshu.com/p/585291fd9226) @[2](http://www.jianshu.com/p/e59bca4a1ac3)
实现推送通知流程:
 - 1.登录开发者中心,点击推送证书功能
 - 2.由于一个开发者账号只能在一个机器上使用,需要废除原来注册的账号,重新注册。Certificate->All->Developer -> iOS App revoke
 - 3.上传生成的CSR文件-> 下载证书(1)
 `注意:留意OSX的WWDR根证书是否已经过期,如果过期,需要到Apple开发者中心下载并重新安装` 
 - 4.生成配置AppIDs推送证书,到Apple开发者网站申请一个应用的标识(也叫套装id)
步骤:Identifiers->AppIDs->"+"->填写App描述->填写BundleID->勾选需要服务(Push Notifications)(2)
 - 5.添加了App ID后,利用AppID创建开发阶段推送证书Certificate -> Development  -> "+" -> 选择"Apple Push Notification Server" SSL -> 选择这个推送证书所对应的App ID -> CSR文件上传以及下载
 - 6.申请发布证书
 - 7.添加测试设备:Device (在X-code 的windon中可以查看真机ID)-> 结合真机+应用ID 生成证书

##3.[极光推送](https://www.jpush.cn)
 - 1 注册账号
 - 2 获取APPKEY APPSECRET使用从Apple获得的两个证书`(产品证书&推送证书)`,在钥匙串中导出 ".p12" 类型证书
 - 3 按照官方sdk文档配置 导入lib 导入依赖的框架 设施PushConfig.plish 拷贝相应代码到APPDelegate.h中
  - 3.1 导入SDK开发文件,将解压后的lib子文件夹(包含APService.h、libPushSDK.a)添加到你的工程目录中)
  - 3.2 导入框架
```
CFNetwork.framework
CoreFoundation.framework
CoreTelephony.framework
SystemConfiguration.framework
CoreGraphics.framework 
Foundation.framework
UIKit.framework
Security.framework
libz.dylib
```

  - 3.3 创建并配置PushConfig.plist文件
        在工程中创建一个新的PropertyList文件,并将其命名为PushConfig.plist,填入Portal为你的应用提供的APP_KEY等参数

    ```
    "APS_FOR_PRODUCTION = "0"; 
    "CHANNEL" = "Publish channel";
    "APP_KEY" = "AppKey copied from JPush Portal application";
    ```
  - 3.4 代码转移

##8. 产品上架
  - 1 [在开发者网站](https://developer.apple.com)申请一个App id(套装id)
  - 2 修改bundleid和注册的id一致
  - 3 登录 [iTunes Connect](https://itunesconnect.apple.com) ->我的APP -> 新建APP工程(提交Appid)
  - 4 打包产品:通用设备或者真机 ->Product ->Archive
  - 5 返回 [iTunes Connect](https://itunesconnect.apple.com) 填写应用信息

移动开发过程:
1.了解需要实现功能,什么类型 2.产品经理估价 工期评估 3.签订合同 4. 形成效果图UI/UE (客户确认) 5.正式研发阶段

移动应用开发步骤:
    1. 规划UI  2. 设计数据操作与存储 3. 跳转多页面实现 4. 实现功能 5. 完善特性与细节 6. 移动应用程序测试 7. 打包签名发布
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知...
    莫离_焱阅读 6,489评论 1 8
  • “推送通知?喔,不!”。是的,这就是我被叫去实现一个 iOS 应用中的推送通知功能时,脑海中闪过的第一念头,而且我...
    王小宾阅读 2,731评论 0 2
  • 作者:Gabriel Theodoropoulos,原文链接,原文日期:2016-01-27译者:bestswif...
    梁杰_numbbbbb阅读 1,233评论 1 14
  • 来源:崔江涛的博客 概述在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感...
    李栖桐阅读 922评论 0 0
  • 对床的舍友刚刚和男友大吵了一架,整个宿舍尴尬的有点过分。宋歌起身倒了杯热水,递给这个满面梨花的姑娘。也许在这个时候...
    林之初阅读 568评论 0 1