精华内容
下载资源
问答
  • iOS 开发之实现 App 消息推送(最新)

    万次阅读 多人点赞 2014-11-19 21:13:10
    今天就由本菜鸟给大家做一个简单的IOSApp消息推送教程吧!一切从0开始,包括XCode6, IOS8, 以及苹果开发者中心最新如何注册应用,申请证书以及下载配置概要文件,相信很多刚开始接触ios的人会很想了解一下。(ps:...

    好久没有写过博客啦,今天就由本菜鸟给大家做一个简单的IOSApp消息推送教程吧!一切从0开始,包括XCode6, IOS8, 以及苹果开发者中心最新如何注册应用,申请证书以及下载配置概要文件,相信很多刚开始接触ios的人会很想了解一下。(ps:网上看了一下虽然有很多讲述推送的好教程,我也是看着一步步学会的,但是这些教程的时间都是去年或者更早时期的,对引导新手来说不是很合适)

    第一部分

    首先第一步当然是介绍一下苹果的推送机制(APNS)咯(ps:其实每一篇教程都有),先来看一张苹果官方对其推送做出解释的概要图。

    Provider是给你手机应用发出推送消息的服务器,而APNS(Apple Push Notification Service)则是苹果消息推送服务器。你本地的服务器当需要给应用推送一条消息的时候,先要将消息发出到苹果推送服务器,然后再由苹果推送服务器将消息发到安装了该应用的手机。

    接下来再看一张解释图:

     

    根据上图的逻辑我来给大家解释一下:

    1.你的IOS应用需要去注册APNS消息推送功能。

    2.当苹果APNS推送服收到来自你应用的注册消息就会返回一串device token给你(很重要)

    3.将应用收到的device Token传给你本地的Push服务器。

    4.当你需要为应用推送消息的时候,你本地的推送服务器会将消息,以及Device Token打包发送到苹果的APNS服

    5.APNS再将消息推送给目的iphone

     

    第二部分

    1.从证书颁发机构颁发证书

    打开你mac的钥匙串访问: 然后点击钥匙串访问

     

    随后它会弹出一个窗口用户电子邮件信息就填写你苹果开发者账号的名称即可(应该是一个邮件名称),点击保存到磁盘的选

    项,点击继续,显示如下:

     

    点击存储,文件名为:CertificateSigningRequest.certSigningRequest 随后将他放在一个文件夹中我们取名push吧!

     

    第三部分

    访问苹果开发者网址:https://developer.apple.com/

     

    选中MemberCenter选项,进入登陆页面,用你的苹果开发者账号登陆,过一会网页就会自动跳转到下图。

    点击红色所选部分内容进行下一步的操作。

    选择Certificates选项,设置证书,如图所示先解释一下:

     

     

    Development选项的作用顾名思义就是用来作为开发使用的证书,Production选项则是用来发布产品使用的,名称很陌生是不是,之

    前的开发者网页是没有这一选项的,可能是苹果把他修改了,用这个名称更加能让人理解吧(字面上解释就是产品么)。两个选项生

    成证书的步骤是一样的,现在我们使用开发者的选项进行证书的制作,步骤如下:选择Development选项:

     

    点击上面的加号选项,

     

    选择APNS选项(开发么当然是在沙盒环境下了,模拟真实情况),然后Continue

     

    这个AppID我们在下一部分讲如何生成,现在我用的是已经生成好的一个应用ID,继续Continue

     

    这边就要选择在钥匙串访问环节下载下来的CertificateSigningRequest.certSigningRequest文件了,选择并生成:

    点击下载,得到aps_development .cer,保存到push文件中去。

     

    第四部分

    新建一个AppID,选择网页上的AppIDs,然后点击右上角的 “加号”

     

    App的取名只要按照苹果要求的就可以了

     

    然后BundleID是比较重要的,在提交审核以及测试(苹果的TestFlight)和付费环节都需要用到,也只需按照苹果要求来写就好了。

     

    接下来就是对你的应用需要使用苹果的哪些服务进行选择就行了,例如广告,游戏中心,推送,付费等等情况。

    最后选择“Submit”选项,在下一个界面中选择“done”选项,这样我们设置AppID的步骤我们就完成了。


    第五部分:生成Provisioning Profiles

    这个配置概要文件分为两种,一种是为开发使用的,还有一种则是为发布到appStore上面。

    创建发布版的ProvisioningProfile与开发版的流程相同,点击Development然后点击右上角的加号

     

    会进入选择何种配置概要文件的界面:

     

    我们现在时测试,所以选择“IOS App Development”的选项,在下面的Distribution发布选项中有两个选择,“App Store”以及

    “Ad hoc”,你可以根据下面的描述选择你发布所需的选项。点击Continue进入下一步。

    选择你上一步创建的AppID,点击Continue 进行下一步

    选择你的开发者账号,Continue进行下一步

    在这一步上选择你的设备(你只有在这一步上勾选了你的设备,你才能在设备上用这个签名进行调试)。关于如何将你的设备号添加

    进去也是非常简单的,选择左侧的"Devices",然后点击右上角的加号,在随后出来的页面上添加你设备的UUID(在XCode中可以查

    看到)以及name( 可以随便取,自己看的懂就行)然后Register一下,照着流程走到最后一步就完成了。

    好咱们继续回到上面的Provisioning Profile配置环节,当你选好了你的设备后点击“Continue”进入下一页,

     

    输入一个文件名(最好是起的能看懂是干嘛的,当然也可以随便起),点击“Generate”进入下一个页面,在这个页面中就会有一个下

    载按钮让你下载这个文件,我们把它下载下来放在Push文件夹中。

     

    第六部分

    好了,前期的准备工作都已经做完了,现在让我们开始推送吧!(吼吼)

    首先双击我们生成的 “aps_development .cer” 文件,进入钥匙串访问,找到我们的专用秘钥(根据在第二部分中从证书机构颁发证书操作中填写的常用名)

     

    我在第二部分填写的是“silicon”,由于换了一台mac之前安装的没有了,之前没有截图,所以随便找了个图给大家看一下,凭大家的聪明才智应该不难理解吧。

    然后右击导出,会弹出如下所示的图。

     

    将他存储到push文件夹中,命名为“push.p12”,在这一步中导出会让你输入密码并验证,你可以自定义一个密码,例如abc123

    现在push文件夹中应该有几个文件“aps_development .cer” ,"push.p12",“CertificateSigningRequest.certSigningRequest”以及

    刚才下下来的配置概要文件。

     

    接下来我们打开终端将他们生成.pem文件

    1.把aps_development .cer文件生成.pcm文件,cd到push文件夹下

     

    2.把push.p12文件生成为.pem文件

    上边输入的密码则是你导出证书所设的密码,即abc123.接着还会让你输入.pem文件的密码,还是使用abc123好了,防止混淆。

    这样我们在push文件夹中就又得到了两个文件,PushChatCert.pem和PushChatKey.pem。

     

    3.把PushChatCert.pem和PushChatKey.pem合并为一个pem文件,

     

    在push文件夹中又多了一个ck.pem文件,以上我们把需要使用的文件都准备好了

     

    接下来就要测试一下啦,是不是很激动~

    为了测试证书工作的状况,我们可以使用“telnet gateway.sandbox.push.apple.com 2195”来检测一下,如果显示下图则表示成功了。

     

    然后,我们使用我们生成的证书和私钥来设置一个安全的链接去链接苹果服务器

    在终端输入如下命令:openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem

    需要输入密码(abc123 我们刚才所设置的)。

    然后他会返回一系列的数据,这里我就粘贴一部分啦:

     

    CONNECTED(00000003)

    depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C

    verify error:num=20:unable to get local issuer certificate

    verify return:0

    ---

    Certificate chain

    。。。。。(省略)

    。。。。。(省略)

    。。。。。(省略)

     

        Start Time: 1416389389

        Timeout   : 300 (sec)

        Verify return code: 0 (ok)

    ---

    测试就到这里啦。。。

     

    第七部分

    1.建立推送项目

     

    //
    //  AppDelegate.m
    //  TestPushNotifiy
    //
    //  Created by silicon on 14-10-30.
    //  Copyright (c) 2014年 silicon. All rights reserved.
    //
    
    #import "AppDelegate.h"
    
    @implementation AppDelegate
    @synthesize mainView = _mainView;
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
        {
            //IOS8
            //创建UIUserNotificationSettings,并设置消息的显示类类型
            UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];
            
            [application registerUserNotificationSettings:notiSettings];
            
        } else{ // ios7
            [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge										 |UIRemoteNotificationTypeSound										 |UIRemoteNotificationTypeAlert)];
        }
        
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // Override point for customization after application launch.
        self.window.backgroundColor = [UIColor whiteColor];
        [self.window makeKeyAndVisible];
        
        self.mainView = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
        self.window.rootViewController = self.mainView;
        return YES;
    }
    
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{
        NSLog(@"---Token--%@", pToken);
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
        
        NSLog(@"userInfo == %@",userInfo);
        NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
        
        [alert show];
    }
    
    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    
        NSLog(@"Regist fail%@",error);
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application
    {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
    
    @end
    

     

    在appdelegate.m中加入以上代码,

     

     

     

    if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
        {
            //IOS8
            //创建UIUserNotificationSettings,并设置消息的显示类类型
            UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];
            
            [application registerUserNotificationSettings:notiSettings];
            
        } else{ // ios7
            [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge										 |UIRemoteNotificationTypeSound										 |UIRemoteNotificationTypeAlert)];
        }

    由于ios8的推送跟ios7及以下的不一样,所以需要加判断来注册消息推送。

    函数:

     

    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{
        NSLog(@"---Token--%@", pToken);
    }

     

    会接收来自苹果服务器给你返回的deviceToken,然后你需要将它添加到你本地的推送服务器上。(很重要,决定你的设备能不能接收到推送消息)。

     

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
        
        NSLog(@"userInfo == %@",userInfo);
        NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
        
        [alert show];
    }

     

    这个函数则是当设备接收到来自苹果推送服务器的消息时触发的,用来显示推送消息。

     

     

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    
        NSLog(@"Regist fail%@",error);
    }

    当注册失败时,触发此函数。

     

     

    2.PHP服务端

    将simplepush.php这个推送脚本也放在push文件夹中

     

    <?php
    
    // ??????????deviceToken???????????????
    $deviceToken = 'c95f661371b085e2517b4c12cc76293522775e5fd9bb1dea17dd80fe85583b41';
    
    // Put your private key's passphrase here:
    $passphrase = 'abc123';
    
    // Put your alert message here:
    $message = 'My first push test!';
    
    
    
    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
    stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
    
    // Open a connection to the APNS server
    //??????????
     //$fp = stream_socket_client(?ssl://gateway.push.apple.com:2195?, $err, $errstr, 60, //STREAM_CLIENT_CONNECT, $ctx);
    //?????????????appstore??????
    $fp = stream_socket_client(
    'ssl://gateway.sandbox.push.apple.com:2195', $err,
    $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
    
    if (!$fp)
    exit("Failed to connect: $err $errstr" . PHP_EOL);
    
    echo 'Connected to APNS' . PHP_EOL;
    
    // Create the payload body
    $body['aps'] = array(
    'alert' => $message,
    'sound' => 'default'
    );
    
    // Encode the payload as JSON
    $payload = json_encode($body);
    
    // Build the binary notification
    $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
    
    // Send it to the server
    $result = fwrite($fp, $msg, strlen($msg));
    
    if (!$result)
    echo 'Message not delivered' . PHP_EOL;
    else
    echo 'Message successfully delivered' . PHP_EOL;
    
    // Close the connection to the server
    fclose($fp);
    ?>

    deviceToken填写你接收到的token,passPhrase则填写你的ck.pem设置的密码。

    此刻就是见证奇迹的时候了,使用终端进入到push文件夹,在终端输入 php simplepush.php

     

    若显示以上提示则表示推送成功了。附上一张成功图。

     

    推送就到这边吧!

    感谢这篇博客的指导:http://blog.csdn.net/showhilllee/article/details/8631734

     

    simplepush.php以及XCode工程我会上传到我的资源里去,大家可以去那边下载。有什么不明白的地方大家可以留言或者私信我,我会第一之间回复的~

     

     

    大家可以关注我的微信公众号与我互动,相关问题也可以直接用公众号联系我:

     

     

     

     

     

     

     

     

     

     

    展开全文
  • iOS开发详解

    2019-12-23 11:53:20
    iOS开发详解
  • iOS开发课程套餐

    2020-11-30 10:40:40
    iOS开发套餐超值合集,包含《iOS移动开发从入门到精通》、《Swift5语言入门实例教程》、《使用Objective-C进行iOS移动开发》、《SwiftUI入门到实战》、《iOS开发中的神兵利器》五门课程,合计1040节海量视频课程!...
  • iOS开发指南》(第二版 iOS7)源码

    千次下载 热门讨论 2014-03-20 11:11:59
    ios开发指南:从零基础到app store上架(第2版)》采用全新的ios 7 api,详细介绍了最新的ios 7 开发相关的知识点。本书共分为4 个部分:第一部分为基础篇,介绍了ios 的一些基础知识;第二部分为网络篇,介绍了ios ...
  • iOS开发实战精讲

    万人学习 2015-02-28 10:01:18
    本课主要介绍iOS实际开发的重要的知识点,帮助开发者打通从项目到发布的各个流程与环节,后你会了解iOS开发其实也是很容易的。
  • IOS开发界面设置指南-IOS开发

    千次阅读 多人点赞 2012-03-12 14:48:56
    IOS开发界面设置指南 http://download.csdn.net/detail/iukey/4133785
    展开全文
  • ios开发--基础班视频

    万人学习 2016-06-27 16:10:22
    ios开发基础班视频涵盖了iOS开发的基础知识,iOS开发产品,iOS开发的模块。
  • iOS开发从入门到精通 [2021版]

    千人学习 2019-12-04 20:03:52
    【课程特点】 学习iOS开发,请选本套课程,理由如下: 1、233节大容量课程:包含了iOS开发中的大部分实用技能; 2、创新的教学模式:手把手教您iOS开发技术,一看就懂,一学就会; 3、贴心的操作提示:让您的眼睛...
  • iOS开发学习路线

    千次阅读 2018-04-23 09:37:26
    初级iOS开发iOS中级开发说白了,就是你学会了基本的UI界面搭建,上架,沉淀一段时间,你觉得自己还适合这门行业,还适合,还能接受 这个所谓的iOS开发工程师的行业.你就可以说是一名中级iOS开发. 这个沉淀时间 大约在1年...

    初级iOS开发

    iOS中级开发说白了,就是你学会了基本的UI界面搭建,上架,沉淀一段时间,你觉得自己还适合这门行业,还适合,还能接受 这个所谓的iOS开发工程师的行业.你就可以说是一名中级iOS开发.
    这个沉淀时间 大约在1年的实际工作中,就可以完成.
    如果你觉得这门行业不适合你,请仔细结合自身情况,是否转另一门计算机语言,还是彻底转行.
    是否了解AFNetworking 的实现原理
    是否了解SDAutolayout/Masonry 一种布局库的原理
    是否能够处理基本的iOS崩溃原因/无法编译原因/无法上架原因?
    是否拥有了一定的工作效率,稳定的工作效率.(而不是说,上面派了一个活下来,忙都忙不完,天天加班,还一堆bug)
    是否能够处理第三方库引起的崩溃.
    是否可以很好的融入工作环境,完成每一阶段的工作指标,而不会让自己疲惫不堪.
    Xcode的使用
    第三方库的灵活使用
    AFN
    MJRefresh
    各种网站的使用
    说明:作为一名初级的iOS开发,你需要具备以下技能
    必备技能(全部都会的情况下查看下一项)
    如何判断是否可以升阶
    结论

    中级iOS开发

    如何判断是否可以升阶
    结论
    应用的内存处理
    应用的推送处理
    应用的模块化/单元测试
    应用的第三方集成/集中化管理/稳定迭代
    阅读强大的第三方源码/拥有快速上手新的第三方库的能力.
    能够接受各种新功能的开发(这里是指,即使你没有做过,但是你仍然可以凭借着学习,解决任何业务需求:例如:蓝牙.AR.摄像头.硬件交互.等)
    清楚明白数据的传递方式,应用与后台如何交换数据,交换数据的过程,结果,格式.
    多线程的灵活使用.
    各种并发事件的处理/以及界面的合理性/流畅度
    设计模式的灵活使用.
    说明:作为一名中级的iOS开发,你需要具备以下技能
    必备技能(全部都会的情况下查看下一项)

    高级iOS开发

    应用的组件化/架构分层
    数据结构,操作系统,计算机网络都有自己的了解和认知
    Shell脚本/python/Ruby/JS 至少会一种.
    说明:作为一名高级的iOS开发,你需要具备以下技能(我不是高级开发,所以这里只能给你们提供建议.)
    必备技能

    详细学习路线

    学习路线
    简介
    这里只简单阐述一些概念性的东西,以及学习路线规划,真正的知识请从iOS基础知识点往下开始看.
    Objective-C
    介绍
    概念
    编译原理
    程序启动原理
    结束程序.
    监听系统事件
    Info.plist
    .pch
    App组成
    打开程序
    执行main函数
    执行UIApplicationMain函数
    初始化UIApplication(创建设置代理对象,开启事件循环)
    语法.(此处定义可能略失严谨,口头教学为主)
    基础语法
    对象.
    属性
    数据类型
    方法
    继承
    Frame/CGRect/CGPoint和CGSize
    内存(针对MRC下情况进行介绍)
    ARC/MRC
    弱引用/强引用
    Assign,retain,copy,strong
    import 和@class的区别
    Xcode使用
    首先是针对Xcode菜单栏,希望自己可以去翻译一下每个菜单里每项功能的英文都是什么意思,有助于自己熟悉并加深印象的使用Xcode.
    熟悉Xcode的各个功能.
    UIKit控件.
    界面分析(下载App进行学习).
    界面适配
    在这里推荐有兴趣的开发人员,下载并分析,AppStore中的每项分类的top50的应用,多学习大公司以及流行应用是如何开发应用的,其中流行的,新颖的开发界面的方式可以总结下来,猜想在大应用中,别的程序员是如何开发的.
    代码架构.
    代码架构文章推荐:https://casatwy.com/iosying-yong-jia-gou-tan-kai-pian.html
    各种工具、第三方的使用.
    其实每个项目的建立都大致分为:项目框架搭建,原生界面搭建,嵌入第三方库.有很多功能都会用到第三方库,大多数第三方库都是本着快速开发,完整功能实现的目的存在的.需要开发人员能够根据业务逻辑不同,选择最好最优质的第三方库进行使用.
    代码封装
    当使用较多第三方库后,要求开发人员学习其开发特点,以及其封装手法,运用在自己的项目上,封装自己的代码.灵活运用.
    完整项目.
    开发技巧
    个人心得

    iOS基础知识点

    iOS基础知识点
    如何学习iOS
    开始涉猎不止于iOS领域中的知识,会去了解相关职位的基础知识,例如前端和后台或者服务器运维,或者项目相关知识,具体往自己的职业规划靠拢
    多看开源或者注明的第三方库.
    收藏并阅读各种大神的博客或者论坛.
    开始考虑项目中的细节优化,内存处理和耗电情况
    打好基础,学习OC中各种常用语法.
    学习如何上架,上架会因为什么被拒,了解App上架规则.
    多学习官方说明文档.
    刚刚入门(如何学习)
    刚刚入职1年(如何稳定)
    入职3年(如何进阶)
    框架的学习
    AFNetworking
    SDAutoLayout
    YYKit
    SDWebImage
    MJRefresh
    MJExtension
    Bugly
    Qiniu
    Masonry
    TZImagePickerController
    Hyphenate_CN
    第三方框架
    苹果自带框架
    基础UI控件
    UILabel 标题栏
    UIButton 按钮
    UIImageView 图片视图
    UITextField 文本输入框
    UITextView 文本展示视图
    UIProgressView 进度条
    UISlider 滑动开关
    UIGesture 手势
    UIActivityIndicator 菊花控件
    UIAlertView(iOS8废除) 警告框
    UIActionSheet(iOS8废除) 操作表单
    UIAlertController(iOS8出现) 警告视图控制器
    UIScrollView 滚动视图
    UIPageControl 页面控制器
    UISearchBar 搜索框
    UITableView 表视图
    UICollectionView集合视图
    UIWebView网页浏览器
    UISwitch开关
    UISegmentControl选择按钮
    UIPickerView选择器
    UIDatePicker日期选择器
    UIToolbar工具栏
    UINavigationBar通知栏
    UINavigationController通知视图控制器
    UITabbarController选择视图控制器
    UIImagePickerController相册
    UIImage图片
    Xcode的使用
    内存监测
    全局断点
    全局搜索替换
    界面适配
    StoryBoard
    界面预览
    基础操作 状态栏
    偏好设置
    Xcode Source Control 源代码管理器
    Xcode workSpace工作组
    Xcode Scheme 计划
    Xcode AutoLayout 约束
    Xcode CoreData数据库
    LLDB 断点调试
    数据存储
    沙盒存储
    NSDictionary归档
    NSUserDefault
    CoreData
    NSKeyedArchiver
    SQLite
    FMDB
    plist
    App生命周期
    alloc
    init
    创建View
    ViewDidLoad
    ViewWillAppear
    ViewDidAppear
    ViewWillDisappear
    ViewDidDisappear
    视图将要消失 (做一些视图将要消失时的UI的处理)
    视图已经消失 (做一些视图消失之后数据的处理)
    viewDidDisappear销毁定时器
    dealloc
    didReceiveMemoryWarning
    控制器生命周期
    应用生命周期
    开发者账号&上架流程
    个人
    公司
    企业
    https://www.jianshu.com/p/6601a241da8e
    https://www.jianshu.com/p/7c98651d3532
    https://www.jianshu.com/p/9b994a019ee6
    文章推荐:
    常用知识
    响应链
    异常捕捉
    国际化
    代码模块化
    类别/扩展
    iPad与iPhone的区别
    静态库
    内存管理
    Quartz2D
    真机调试
    isKindOfClass 与 isMemberOfClass
    Return/Break/Continue
    Core Animation
    CALayer
    AutoLayout
    KVC/KVO
    谓词NSPredicate
    帧动画
    界面旋转+状态栏隐藏
    plist文件
    通信
    NS系列
    宏定义
    视图层次
    切换视图
    深浅拷贝
    对象序列化
    写入文件
    获取沙盒路径
    翻转视图
    延伸视图
    九大基本数据类型
    九宫格
    坐标比较
    UIColor 、CIColor和CGColor 之间的关系
    画图
    静态变量
    tag值
    延时执行方法

    中级知识点

    设计模式
    UIScrollView/UITableView/UICollectionView 的嵌套
    动态行高
    通知/代理/block
    程序启动原理
    触摸事件/手势
    图文混编
    Runtime
    NSRunLoop
    GCD
    ReactiveCocoa开发
    3DTouch
    界面渲染
    Charles花瓶抓包
    区分模拟器/真机项目
    常用知识
    Block
    蓝牙/传感器
    物理仿真器UIDynamic
    通讯录获取
    音频/视频/二维码
    真机调试
    苹果内购/广告
    推送/远程推送
    单例模式
    多线程
    网络请求
    定位
    源代码管理Git

    iOS高级知识点

    iOS高级知识点
    Socket
    XMPP
    加密
    MD5详解
    Base64加密解密
    RSA非对称加密
    AES对称加密
    音频
    基础
    Core Audio
    Audio Toolbox
    OpenAL
    AVFoundation
    Speex语音聊天
    AudioQueue/AudioSession
    Speex简介
    视频
    AAC视频.H264推流
    P2P传输
    直播
    RTMP协议
    RTMP直播应用与延时分析
    如果做一款inke版的App
    推流发布和播放RTMP
    FFmpeg
    基于FFmpeg的推流器
    HLS流媒体传输协议(HTTP Live Streaming)
    FFmpeg
    ijkPlayer
    直播的技术分析与实现
    算法
    简介
    冒泡排序
    快速排序
    插入排序
    归并排序
    二分查找
    希尔排序
    动态规划
    堆排序

    官方Kit

    ARKit.
    SiriKit
    HealthKit
    HomeKit
    SearchKit
    IOKit
    PDFKit
    CloudKit
    GameplayKit
    SpriteKit
    SceneKit
    MusicKit
    ResearchKit
    MapKit
    StoreKit
    AVKit

    展开全文
  • iOS 开发之 In-App Purchase 对接教程 (一)

    万次阅读 多人点赞 2015-01-15 15:25:26
    很久之前就想出一篇IOS内付费的教程,但是一查网上的教程实在太多了,有的写得真的蛮不错的......进入苹果的ItunesConnection(https://itunesconnect.apple.com)点击左上角的加号新建一个App应用..

    很久之前就想出一篇IOS内付费的教程,但是一查网上的教程实在太多了,有的写得真的蛮不错的,就心想算了,于是就保存在草稿箱了。至于为什么写完它呢!真是说来话长,最近公司有个项目经理跑来问我有关苹果内付费相关的细节,跟他聊了半天,从项目对接苹果官方支付接口聊到了如何查看App收益,最后终于使他有了一些眉目,但是悲催的是还要我继续去跟他们项目的程序员讲解(真是疯了),所以我就决定给他们项目写一个内购的文档,所以我顺便把这篇博客完成吧!

     

    首先进入苹果的ItunesConnection(https://itunesconnect.apple.com)点击左上角的加号新建一个App应用,点击后该网站会弹出一个信息编辑框,大家只要将上面的信息填充完毕点击save即可在苹果的app平台上拥有一个属于自己的App。

     

     

    在套装ID的上,需要提前为该App申请一个AppID以及BundleID,只要是申请成功了就会在选择列表中显示出来。如果有人有疑问如何申请,请看我之前那一篇推送的博客,里面有详细的步骤。附上链接点击打开链接

    这里顺便多说一句这个ItunesConnect是用来干嘛的,它是苹果公司给个人或企业提供管理自己App的一个平台。在这个平台上开发者可以新建,删除和管理自己的App应用,开发者可以根据需求对App应用进行上架与下架,编辑App信息,生成测试app所需的信息,例如账号,邀请码等,还有就是我们今天要讲的内付费功能。当然啦,他的功能可不止我讲的这些,我大致说一下这个平台的作用,如果你经常跟它打交道的话就会慢慢熟悉了。

     

    接下来,我就来为大家演示一下如何添加付费道具,首先打开iTunesConnect,显示如下页面:

     

    选择红圈所圈起来的选项,然后将里面的相关信息补充完毕,如果缺少这一步,内购功能是不会成功的。

    假如你已经完成了上述相关银行账户的设置,就点击你的App,选择上面标题栏中的"App 内购买项目"

     

    随后点击左上角的 "create new"选项,如下图所示,进入到下一个界面:

     

     

    这个界面是让你选择消费道具的种类,现在改版的网站是有简体中文翻译的,所以不像以前打开一看都不知道选哪一个,甚至都不知道每个代表的什么意思(比如我第一次遇到的时候,在领导面前真是囧)。它的种类分为如下几种:

     

     

     

    一般对项目来说大多数都是选择“消耗型项目”这个种类,比如游戏中购买金币,宝石balabala~之类的,选中之后就会到这个界面中来:

     

    在上图所示的编辑框中输入,商品名称,产品ID以及价格等级,在这边说明一下:

    1.商品名称根据你的消费道具的实际意义来说明,比如“100颗宝石”,“100金币”等。

    2.产品ID是比较重要的,由项目自定义,只要唯一即可,像我一般都是用App的bundleID加一个后缀来表示,这样既跟项目关联又具有唯一性。

    3.价格等级的话“查看价格表”中有对应的说明,可以对照着表中每个国家的货币价格与等级来选择。

     

    我们继续,在这个网页的接下来部分如图所示:

     

    选择添加语言选项,弹出一个编辑页面:

     

    点击save保存,则会在界面上显示成如下:

     

    最后一步就是点击“选取文件”提交一张苹果它指定像素(640*920)的商品图片,当他上传完毕后点击“save”按钮,我们这第二部分就大工告成了。提交的商品最后会在内购的页面上显示为如图:

     

    这个图是我在已经发布的app上面截取的,添加了3个商品,已经是通过的的状态了(显示绿色),当您刚提交的时候,因为通过苹果的审查需要一段时间所以会显示黄色的等待状态,所以不必担心是不是商品编辑错了。如图:

     

     

    这部分,我主要给大家演示一下,如何申请测试账号,利用苹果的沙盒测试环境来模拟AppStore的购买流程。

    在ItunesConnect中选择“用户和职能”选项~

     

     

    随后在左上角的选项中选择沙盒测试者,点击左上角的加号图标增加一位测试者,如图:

    编辑好相应的内容,点击保存,就创建了一个测试账号,是不是很简单啊!当然这个账号如果你忘记了密码可以重新生成一个,无关紧要。

    顺带多句嘴,不要在正式的appstore上面用沙盒测试的账号来登录,千万要牢记在心,此账号只用于测试环境下~

     

    接下来就是代码部分啦~

    1.首先在项目工程中加入“storekit.framework”,加入头文件#import <StoreKit/StoreKit.h>

    2.在.h文件中加入“SKPaymentTransactionObserver,SKProductsRequestDelegate”监听机制

    下面贴上内购的核心代码,就几个函数,我在这边就不在做更多详细的解释了,各位看官可以运行跑一下就一目了然了。

    .h文件

     

    //
    //  PaymentViewController.h
    //  IAPPayTest
    //
    //  Created by silicon on 14-10-28.
    //  Copyright (c) 2014年 silicon. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    #import <StoreKit/StoreKit.h>
    
    @interface PaymentViewController : UIViewController<SKPaymentTransactionObserver,SKProductsRequestDelegate>
    
    @property (strong, nonatomic) IBOutlet UITextField *productID;
    
    @property (strong, nonatomic) IBOutlet UIButton *purchase;
    
    - (IBAction)purchaseFunc:(id)sender;
    
    @end

     

    .m文件

     

     

    //
    //  PaymentViewController.m
    //  IAPPayTest
    //
    //  Created by silicon on 14-10-28.
    //  Copyright (c) 2014年 silicon. All rights reserved.
    //
    
    #import "PaymentViewController.h"
    
    @interface PaymentViewController ()
    
    @end
    
    @implementation PaymentViewController
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view from its nib.
        
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        self.productID.text = @"com.games.ztyxs.product_point.1";
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (IBAction)purchaseFunc:(id)sender {
        NSString *product = self.productID.text;
        if([SKPaymentQueue canMakePayments]){
            [self requestProductData:product];
        }else{
            NSLog(@"不允许程序内付费");
        }
    }
    
    //请求商品
    - (void)requestProductData:(NSString *)type{
        NSLog(@"-------------请求对应的产品信息----------------");
        NSArray *product = [[NSArray alloc] initWithObjects:type, nil];
    
        NSSet *nsset = [NSSet setWithArray:product];
        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
        request.delegate = self;
        [request start];
        
    }
    
    //收到产品返回信息
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
        NSLog(@"--------------收到产品反馈消息---------------------");
        NSArray *product = response.products;
        if([product count] == 0){
            NSLog(@"--------------没有商品------------------");
            return;
        }
        
        NSLog(@"productID:%@", response.invalidProductIdentifiers);
        NSLog(@"产品付费数量:%d",[product count]);
        
        SKProduct *p = nil;
        for (SKProduct *pro in product) {
            NSLog(@"%@", [pro description]);
            NSLog(@"%@", [pro localizedTitle]);
            NSLog(@"%@", [pro localizedDescription]);
            NSLog(@"%@", [pro price]);
            NSLog(@"%@", [pro productIdentifier]);
            
            if([pro.productIdentifier isEqualToString:self.productID.text]){
                p = pro;
            }
        }
        
        SKPayment *payment = [SKPayment paymentWithProduct:p];
        
        NSLog(@"发送购买请求");
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    }
    
    //请求失败
    - (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
        NSLog(@"------------------错误-----------------:%@", error);
    }
    
    - (void)requestDidFinish:(SKRequest *)request{
        NSLog(@"------------反馈信息结束-----------------");
    }
    
    
    //监听购买结果
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{
        for(SKPaymentTransaction *tran in transaction){
            
            switch (tran.transactionState) {
                case SKPaymentTransactionStatePurchased:
                    NSLog(@"交易完成");
                    
                    break;
                case SKPaymentTransactionStatePurchasing:
                    NSLog(@"商品添加进列表");
                    
                    break;
                case SKPaymentTransactionStateRestored:
                    NSLog(@"已经购买过商品");
                
                    break;
                case SKPaymentTransactionStateFailed:
                    NSLog(@"交易失败");
                    
                    break;
                default:
                    break;
            }
        }
    }
    
    //交易结束
    - (void)completeTransaction:(SKPaymentTransaction *)transaction{
        NSLog(@"交易结束");
        
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    }
    
    
    - (void)dealloc{
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
        [super dealloc];
    }
    
    @end

     

    代码就这么多,到这边我们的IOS内购教程就接近尾声了,在测试的时候还有几点因素要注意一下:

     

     

    1.沙盒环境测试appStore内购流程的时候,请使用没越狱的设备

    2.请务必使用真机来测试,一切以真机为准。

    3.项目的Bundle identifier需要与您申请AppID时填写的bundleID一致,不然会无法请求到商品信息。

    讲了这么多,附上几张测试截屏给大家展示一下:

    请求商品时的打印日志:

    交易成功后:

     

    手机截屏:

    要求输入AppStore帐密,使用测试生成的即可:

     

    确定购买:

     

    交易完成:

     

    当我们的交易完成后还要去appstore 上面去验证票据信息是否正确,这样我们才可以给玩家发放道具,apple官方文档

     

    //交易结束
    - (void)completeTransaction:(SKPaymentTransaction *)transaction{
        NSLog(@"交易结束");
        //交易验证
        NSURL *recepitURL = [[NSBundle mainBundle] appStoreReceiptURL];
        NSData *receipt = [NSData dataWithContentsOfURL:recepitURL];
        
        if(!receipt){
            
        }
        
        NSError *error;
        NSDictionary *requestContents = @{
                                          @"receipt-data": [receipt base64EncodedStringWithOptions:0]
                                          };
        NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                              options:0
                                                                error:&error];
        
        if (!requestData) { /* ... Handle error ... */ }
        
        //In the test environment, use https://sandbox.itunes.apple.com/verifyReceipt
        //In the real environment, use https://buy.itunes.apple.com/verifyReceipt
        // Create a POST request with the receipt data.
        NSURL *storeURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"];
        NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
        [storeRequest setHTTPMethod:@"POST"];
        [storeRequest setHTTPBody:requestData];
        
        // Make a connection to the iTunes Store on a background queue.
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                               completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                                   if (connectionError) {
                                       /* ... Handle error ... */
                                   } else {
                                       NSError *error;
                                       NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                       if (!jsonResponse) { /* ... Handle error ...*/ }
                                       /* ... Send a response back to the device ... */
                                       //Parse the Response
                                   }
                               }];
    
        
        
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    }

     

     

     

     

     

     

     

    好了,所有的内购流程基本上讲完了,原谅我在图片上的涂抹,因为关系到产品的敏感词汇所以希望大家能够不介意。赶这篇博客的时间比较匆忙,如果有童鞋还有什么疑问或者我写的那个地方不对欢迎私信我或者评论,我会在第一时间回复。谢谢~

     

     

    大家可以关注我的微信公众号与我互动,相关问题也可以直接用公众号联系我:

    展开全文
  • iOS开发教程之OC语言

    万人学习 2015-04-01 18:25:25
    Objective-C是扩充C的面向对象编程语言,iOS开发是用的Objective-C语言,本专题更系统的讲解Objective-C语言当中的一些要点,类的封装、基本数据结构(NSString、NSData)、继承、内存管理(retain点语法、MyArray、...
  • swift语言IOS开发PDF

    2015-06-25 15:19:13
    swift语言IOS开发PDF
  • 从零学IOS开发(一)

    万次阅读 2021-05-23 17:03:16
    IOS开发环境很简单,只需一台MAC和一个IDE(Xcode),Xcode是apple官方的开发环境,有了电脑和IDE后就不需要配置任何东西了。Mac挺费米的,不过好在Xcode是免费下载的。 二,新建项目 ​ 新建项目时候需要选择app...
  • iOS开发证书管理

    千次阅读 2017-09-07 23:28:36
    总会报一些错误,有些是语法上的错误,老的代码在新的编译环境下不通过,还有的因为因为签名导致的错误,如常见的错误提示:“Failed to create provisioning profile.”,ios的证书管理是ios开发中必须掌握的技能,...
  • iOS开发进阶完整版 唐巧

    热门讨论 2016-02-26 11:34:15
    这个文档适合那些已经从事了IOS开发的想有更上一步的朋友,里边的内容很全面。
  • 苹果ios开发一年的工作笔记

    热门讨论 2012-02-01 14:39:17
    这份文档是我从事ios开发一年以来,总结工作中常用到的100余个ios小知识点,并添加可以调试观看的实例代码,方便iso开发者学习和交流,弄清楚这些,基本从事ios开发没什么问题。
  • iOS9程序设计(顶级iOS开发视频课程-Objective-C版) 本课程主要内容包括: iOS9的基础知识 常用控件 屏幕适配 多窗口 导航 表视图 GPS 地图 网络 数据存储、 音频 视频 本地化等内容,并提供了大量的源代码供学员...
  • ios开发怎么样啊?

    2020-07-27 14:58:47
    ios开发怎么样啊,据说很困难,不太了解
  • iOS开发之Objective-C编程基础

    万人学习 2015-06-25 13:51:14
    本系列课程视频提供iOS培训之Objective-C基础视频,第一个Obj-C程序 Hello world,面向对象编程,面向过程编程,类和对象,self使用详解, property基础,synthesize基础,...学生从零开始iOS开发的优质视频教程。
  • 手把手学习iOS开发中的强大的第三方类库,详细讲解Github中的热门的iOS开发开源项目。助您快速、优雅地解决iOS开发中棘手的业务需求!   【课程特点】  1、代码逐行讲解 2、语言简洁、精练、瞄准问题的...
  • IOS开发从入门到精通-第一章

    千人学习 2018-04-08 22:16:23
    本课程详细介绍了IOS开发环境搭建及开发工具的使用,讲解了IOS开发常用视图控件的使用 ,还讲解了一个实用的功能实例:APP启动引导页的开发。
  • 这是一套从一个对iOS开发感兴趣的学员到iOS开发高手的系统、专业的课程体系。以培养企业开发真正需要的人才为目标,每个知识点都用案例来讲解。也适合想提升技能的已从事iOS开发的工作人员以最短时间内提升技能的...
  • IOS开发指南(中英版)官方文档

    千次下载 热门讨论 2014-06-30 13:55:19
    IOS开发指南(中英版)官方文档,吐血推荐,极好的资料!
  • iOS开发之Objective-C(基础篇)

    千人学习 2018-01-23 14:16:13
    该系列课程是iOS开发之Objective-C基础入门视频。课程中会详细的讲解OC语法特点,面向对象的使用,循环引用的问题,block的特点及使用,枚举与结构体,Foundation框架等。是针对初级的入门iOS开发的优质视频。
  • IOS 开发官方教程(汉化版)

    千次下载 热门讨论 2013-05-07 19:58:34
    IOS 开发官方教程(汉化版)PDF, 内涵环境搭建、Xcode使用、Object-c入门、设计、框架、开发者申请、应用发布等。
  • 人生最惨的不是被裁员,而是作为一名iOS开发,就因为多看了一眼手机,就被HR开除了… 这是码君今天在脉脉上看到的真事儿,它一直挂在热搜第一,以下是爆料截图—— 码君想说:好家伙,这2021年都过了一半了,真就...
  • 欢迎加入我们的iOS开发交流群

    千次阅读 2016-10-22 22:16:30
    iOS开发交流群。
  • IOS开发环境搭建

    千次阅读 2018-03-31 21:57:16
    当然还可以装一个黑苹果系统,也可以进行IOS开发,但是安装比较复杂,比较难安装成功。二、开发语言准备现在IOS开发有两种主流开发语言:OC和SwiftOC学习门槛比较高一点,Swift学习起来相对简单一些,有面向对象语言...
  • 安装iOS开发环境Xcode

    千次阅读 2015-07-21 21:04:42
    同时对于Android开发来说,iOS开发的环境搭建是比较方便和简单的。下面来简单介绍如何安装Xcode。 (1)登录App Store,在搜索框中输入Xcode,出现以下界面: 。 (2)选择第一个Xcode,进行安装,可见安装Xc

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 467,970
精华内容 187,188
关键字:

ios开发