swift实现一个和智能机器人聊天的app(一)

截图

当 iOS 平台提供了英文拼字检查,但用以 ControlType 设定为 Platform
才能够动用:

公于按照系列文章被以会学到

  • 哪设置以及采用cocoapods来并第三方库
  • 安增加建筑一个看似于iOS短信app的界面,以及用SnapKit来为此代码设置autolayout
  • 怎样使Parse云服务平台存储和旅聊天信息,学习相应地数据库知识
  • 怎么样采取Parse的长距离推送功能
  • 什么利用Alamofire实现同智能机器人聊天功能
    开始项目下载地址:
    百度网盘下载地址

图片 1

布起项目

1.cocoapods的安装
cocoapods的装置是经过ruby,幸运的凡Mac电脑都是默认安装ruby的,所以安装ruby的历程就省去了,唯一的前提就是是安装Xcode的CommandLineTools。
commandLineTools的装置为大粗略,只要以巅峰输入以下命令:

$ xcode-select --install

只要真的并未装commandLineTools会提示而若安装她,点设置就足以起来下载,然后等待下载就后安装即可
下开始设置cocoapods,本来不过需要简单地当巅峰输入以下命令即可:

$ sudo gem install cocoapods

然而由于中国之互联网是”自由之”。。咳咳,所以也,你若改gem的默认下载源:

$ gem sources -a https://ruby.taobao.org

看来以下结果

http://ruby.taobao.org added to sources

用淘宝之ruby源加入进来,看来淘宝为不只是出卖东西哈,也是对准开发者做了有的献的~
除去原来的下载源:

$ gem sources -r https://rubygems.org/

相以下结果就证实已经成

https://rubygems.org/ removed from sources

然后呢,就好喜地设置及cocoapods了!

$ sudo gem install cocoapods

Password:(你的管理员密码,这里不会显示出来)
Fetching: cocoapods-core-0.38.2.gem (100%)
Successfully installed cocoapods-core-0.38.2
Fetching: claide-0.9.1.gem (100%)
Successfully installed claide-0.9.1
Fetching: xcodeproj-0.26.3.gem (100%)
Successfully installed xcodeproj-0.26.3
Fetching: cocoapods-downloader-0.9.3.gem (100%)
Successfully installed cocoapods-downloader-0.9.3
Fetching: cocoapods-stats-0.5.3.gem (100%)
Successfully installed cocoapods-stats-0.5.3
Fetching: cocoapods-try-0.4.5.gem (100%)
Successfully installed cocoapods-try-0.4.5
Fetching: cocoapods-trunk-0.6.4.gem (100%)
Successfully installed cocoapods-trunk-0.6.4
Fetching: molinillo-0.3.1.gem (100%)
Successfully installed molinillo-0.3.1
Fetching: cocoapods-0.38.2.gem (100%)
Successfully installed cocoapods-0.38.2
Parsing documentation for cocoapods-core-0.38.2
Installing ri documentation for cocoapods-core-0.38.2
Parsing documentation for claide-0.9.1
Installing ri documentation for claide-0.9.1
Parsing documentation for xcodeproj-0.26.3
Installing ri documentation for xcodeproj-0.26.3
Parsing documentation for cocoapods-downloader-0.9.3
Installing ri documentation for cocoapods-downloader-0.9.3
Parsing documentation for cocoapods-stats-0.5.3
Installing ri documentation for cocoapods-stats-0.5.3
Parsing documentation for cocoapods-try-0.4.5
Installing ri documentation for cocoapods-try-0.4.5
Parsing documentation for cocoapods-trunk-0.6.4
Installing ri documentation for cocoapods-trunk-0.6.4
Parsing documentation for molinillo-0.3.1
Installing ri documentation for molinillo-0.3.1
Parsing documentation for cocoapods-0.38.2
Installing ri documentation for cocoapods-0.38.2
9 gems installed

OK,cocoapods顺利安装了!
2.cocoapods的使用
那cocoapods怎么用为,当然首先不良以会看它们非常麻烦,但是呢渐渐地而见面发现这是一个格外好用的工具,可以说凡是iOS开发者必要!
率先创建我们的Xcode工程:File/New/Project…/Single View Application
自打名叫图灵聊天。

我们即将利用图灵机器人的api进行付出:
图灵机器人官网

打开项目,新建一个缺损文件:File/New/File…/ iOS/Others/Empty
起名叫Podfile,这无异于碰好主要,因为马上是cocoapods的配置文件,也即是指定你只要以什么第三方库!
俺们要动以下几只仓库:

  • Alamofire,网络要库,用来调用图灵机器人之api
  • SnapKit,用代码进行autolayout设置
  • Parse ,Parse云服务平台的SDK
  • ParseUI,Parse提供的便捷UI组件
    每当Podfile中,输入以下代码:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.4'
use_frameworks!

点名下载源,指定平台版本,使用framework进行集成

是因为swift的特殊性,某些第三方库必须使用framework来拼,但是这样啊有一个利,我哉是近年来才意识,就是Parse和ParseUI其实是OC编写的仓库,但是也却不需OC-Swift的桥接文件了!可以直接当swift库来运!

pod 'Alamofire', '~> 1.3'
pod 'SnapKit', '~> 0.12.0'
pod 'Parse','~>1.7.1'
pod 'ParseUI','~>1.1.3'

分选指定的老三方库及其版本

初步设置第三方库,打开终端,将当前目录转到Podfile所在目:

$ cd <Podfile所在目录>

输入以下命令开始布置第三方库:

$ pod install

Analyzing dependencies
Downloading dependencies
Using Alamofire (1.3.1)
Using Bolts (1.2.1)
Using Parse (1.7.5.3)
Using ParseUI (1.1.4)
Using SnapKit (0.12.0)
Generating Pods project
Integrating client project
Sending stats

接下来等待几分钟,如果一切正常,没有起谬误的说话,打开项目文件后你见面看出workspace的文书,以后都要利用这文件来开辟项目。

图1

开辟项目,看一下列的结构:

品种结构.png

点转Pods项目,你见面发现所要的framework已经编译好了,只要在以前import她们即使可以了:

Pods

OK,到者我们的种就是部署好了,在我们开搭建UI之前,先了解一下Parse的下及有少不了配置

 

配置Parse

先是打开Parse的官网:
点我
登记一个新的用户,点击右侧上较量的sign up :

Parse注册.png

以上用户称只是示例,但是app名称输入TuringChat。
登记了后,用而才注册的用户称登陆,应该会起以下界面:

主界面

下一场导入我们的示范数据:
接触我下载
点击import按钮:

导入数据

选取才下载的公文:

多少导入成功.png

接下来才导入的数就会显示出,并活动新建了一个数量库类:Messages

数据.png

咱们来拘禁无异肉眼Messages类里都有啊:

名称 类型 含义 备注
objectId String 系统默认键 每一条数据都对应一个独一无二的id
incoming Boolean 用来确定该条信息是发送给我们的还是发送出去的 true就是发送来的反之就是我们发送出去的
sentDate Date 消息发送时间
text String 消息的内容
createdAt Date 系统默认键 数据创建时间
updatedAt Date 系统默认键 数据上一次更新的时间
ACL ACL 系统默认键 数据的读写模式

紧接下去我们来测试一下是否读取到这些数据,首先要落该app的application
ID和Client Key:

获取Key

红线划掉的那么片实施就是我们得之。
接下来打开项目面临的AppDelegate.swift,增加对Parse库的援:

import Parse

找到以下措施

  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 

每当里添加代码:

    Parse.setApplicationId("CYdFL9mvG8jHqc4ZA5PJsWMInBbMMun0XCoqnHgf", clientKey: "6tGOC1uIKeYp5glvJE6MXZOWG9pmLtMuIUdh2Yzo")

连日来Parse的服务器

        var query = PFQuery(className: "Messages")
        query.orderByAscending("sentDate")
        query.findObjectsInBackgroundWithBlock { (objects,error) -> Void in
            for object in objects as! [PFObject]{
            let incoming:Bool = object["incoming"] as! Bool
            let text:String = object["text"] as! String
            let sentDate:NSDate = object["sentDate"] as! NSDate
            println("\\(object.objectId!)\\n\\(incoming)\\n\\(text)\\n\\(sentDate)")
        }
     }

新建查询,查询我们才所修的Messages类,用findObjectsInBackgroundWithBlock办法取出查询结果,并为此一个循环全部打印出。
cmd+R运行一下,如果无问题会见输出接近下面的始末:

oYtildSAOz
false
你叫什么名字?
2015-08-28 06:42:00 +0000
LX7kxmmiEp
true
我叫灵灵,聪明又可爱的灵灵
2015-08-28 06:43:00 +0000
p62dmgGIAS
false
你爱不爱我?
2015-08-28 06:43:00 +0000
oWReOM43Nf
true
爱你么么哒
2015-08-28 06:44:00 +0000
mtl2BGt3Mu
false
今天北京天气如何?
2015-08-29 03:59:00 +0000
DikAu5P2Nn
true
北京:08/29 周六,20-29° 28° 雷阵雨 微风小于3级;08/30 周日,19-27° 雷阵雨 微风小于3级;08/31 周一,19-27° 雷阵雨 微风小于3级;09/01 周二,20-26° 雷阵雨 微风小于3级;
2015-08-29 03:59:01 +0000

死好,我们的数据库连接没有问题,那么下面开始搭建我们的UI。

效果:

搭建UI

咱得搭建的UI只是聊天页面,我们首先来拘禁同样拘留聊天页面的组织:
界面主要是因为以下三个组成部分组成

UI结构

那这三有些如何去落实啊,我事先为大家做有简易的牵线:
1.导航栏
立刻无异片实现比较简单,只要拿视图控制器嵌套在一个导航控制器(UINavigationController)中即可,然后针对那个外观进行部分定制化操作。
2.拉窗口
当下无异有的据此UITableView来构建。仔细考察您见面发觉这里一起发生三种植UITableViewCell:

  • 于是来展示信息发送日期的cell
  • 发送信息气泡的cell
  • 接信息气泡的cell
    而是实在我们只有待简单个,因为后少栽cell区别仅是是颜色与位置,我们设判断一下该消息是发送的抑收下的,然后相应进行拍卖即可!
    有限种cell都是用底以下是材料:

    MessageBubble.png

但是,你会问,它为啥是黑色的!怎么让他变成图中的两种颜色呢?还有明明聊天气泡的大小是不定的,这样一张图怎么能满足所有尺寸呢?  
有疑问很好,因为它可以成为你学习的动力,我们会在接下来向大家解释这是如何实现的!Be
patient!  
**3.输入框**  
这里我们要通过重写`UIResponder`类的`inputAccessoryView`属性来自定义我们的输入框,这样做的好处是我们的输入框会和系统的键盘结合起来,可以让其成为第一响应者(first
responder),一旦它成为第一响应者,我们自定义的输入框会跟随键盘一同弹出和收回,就像真正的短信app那样,这个方法比我有一篇文章所写的[实现类似微信的输入框跟随键盘弹出的效果](https://www.jianshu.com/p/4e755fe09df7)的方法还要更好一些,所以说方法不是绝对的,因为你总是能够找到更好的方法,所以,编程的时候要经常在脑子里想"嗯,一定还有更好的方法"。

啊好了,废话不多说,下面我们便来同样步一步地逐一实现其!

首先从太简便的召开打,实现从定义导航栏:
开拓初始项目而会相模板文件已经全建好:
找到AppDelegate.swift文本中之以下办法:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool

每当中添加如下代码:

        var ChatVC:ChatViewController = ChatViewController()
        ChatVC.title = "灵灵"

        UINavigationBar.appearance().tintColor = UIColor(red: 0.05, green: 0.47, blue: 0.91, alpha: 1.0)
        UINavigationBar.appearance().barTintColor = UIColor(red: 0.05, green: 0.47, blue: 0.91, alpha: 1.0)
        UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
        UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.LightContent
        var navigationVC:UINavigationController = UINavigationController(rootViewController: ChatVC)

        let frame = UIScreen.mainScreen().bounds
        window = UIWindow(frame: frame)
        window!.rootViewController = navigationVC
        window!.makeKeyAndVisible()

设置app启动时显得我们从定义的视图控制器,并设置一下导航栏的外观。
ok,第一有的形成。
连下去我们来兑现转老三片:输入框,我们而管极难以的老二组成部分留住于最终( ⊙ o
⊙ )
打开ChatViewController.swift文件:
增长一些大局常量,在import下面class的概念之上:

let messageFontSize: CGFloat = 17
let toolBarMinHeight: CGFloat = 44

先是个是信所用之字体大小,第二单凡是咱输入框的万丈。
添加一些结合输入框的组件:

    var toolBar: UIToolbar!
    var textView: UITextView!
    var sendButton: UIButton!

toolBar用来承载输入框中的零件,之所以用UIToolbar是盖其默认出现在屏幕最下方,就像而的欠信输入框那样。
textView是咱输入文字的地方,而sendButton则是我们的出殡按钮。
下面实现我们再写的inputAccessoryView,在当时前面先让我们的视图控制器遵循UITextViewDelegate协议:

class ViewController: UIViewController,UITextViewDelegate {
....
....
}

下面加加以下代码来声称对inputAccessoryView的重写:

 override var inputAccessoryView: UIView! {

}

所以get的方法拿输入框的组件进行配备:
当大括如泣如诉中添加代码:

        get {
            if toolBar == nil {

                toolBar = UIToolbar(frame: CGRectMake(0, 0, 0, toolBarMinHeight-0.5))

                textView = InputTextView(frame: CGRectZero)
                textView.backgroundColor = UIColor(white: 250/255, alpha: 1)
                textView.delegate = self
                textView.font = UIFont.systemFontOfSize(messageFontSize)
                textView.layer.borderColor = UIColor(red: 200/255, green: 200/255, blue: 205/255, alpha:1).CGColor
                textView.layer.borderWidth = 0.5
                textView.layer.cornerRadius = 5
                //            textView.placeholder = "Message"
                textView.scrollsToTop = false
                textView.textContainerInset = UIEdgeInsetsMake(4, 3, 3, 3)
                toolBar.addSubview(textView)

                sendButton = UIButton.buttonWithType(.System) as! UIButton
                sendButton.enabled = false
                sendButton.titleLabel?.font = UIFont.boldSystemFontOfSize(17)
                sendButton.setTitle("发送", forState: .Normal)
                sendButton.setTitleColor(UIColor(red: 142/255, green: 142/255, blue: 147/255, alpha: 1), forState: .Disabled)
                sendButton.setTitleColor(UIColor(red: 0.05, green: 0.47, blue: 0.91, alpha: 1.0), forState: .Normal)
                sendButton.contentEdgeInsets = UIEdgeInsets(top: 6, left: 6, bottom: 6, right: 6)
                sendButton.addTarget(self, action: "sendAction", forControlEvents: UIControlEvents.TouchUpInside)
                toolBar.addSubview(sendButton)

                // 对组件进行Autolayout设置
                textView.setTranslatesAutoresizingMaskIntoConstraints(false)
                sendButton.setTranslatesAutoresizingMaskIntoConstraints(false)

                toolBar.addConstraint(NSLayoutConstraint(item: textView, attribute: .Left, relatedBy: .Equal, toItem: toolBar, attribute: .Left, multiplier: 1, constant: 8))
                toolBar.addConstraint(NSLayoutConstraint(item: textView, attribute: .Top, relatedBy: .Equal, toItem: toolBar, attribute: .Top, multiplier: 1, constant: 7.5))
                toolBar.addConstraint(NSLayoutConstraint(item: textView, attribute: .Right, relatedBy: .Equal, toItem: sendButton, attribute: .Left, multiplier: 1, constant: -2))
                toolBar.addConstraint(NSLayoutConstraint(item: textView, attribute: .Bottom, relatedBy: .Equal, toItem: toolBar, attribute: .Bottom, multiplier: 1, constant: -8))
                toolBar.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .Right, relatedBy: .Equal, toItem: toolBar, attribute: .Right, multiplier: 1, constant: 0))
                toolBar.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .Bottom, relatedBy: .Equal, toItem: toolBar, attribute: .Bottom, multiplier: 1, constant: -4.5))
            }
            return toolBar
        }

公会意识来一个错误,这是为我们的InputTextView是一个单身定义之好像,它还无概念,我们当此后会针对他做片操作,目前先期不用无它,不过我们先将她定义出来,在视图控制器类之外定义该类:

class InputTextView: UITextView {



}

还有一个题目,用系统默认的代码实现autolayout看起挺为难知晓,所以这边可以就此第三着库SnapKit来促成,把上面设置autolayout的代码替换成以下代码:

textView.setTranslatesAutoresizingMaskIntoConstraints(false)             
sendButton.setTranslatesAutoresizingMaskIntoConstraints(false)

 textView.snp_makeConstraints({ (make) -> Void in

                    make.left.equalTo(self.toolBar.snp_left).offset(8)
                    make.top.equalTo(self.toolBar.snp_top).offset(7.5)
                    make.right.equalTo(self.sendButton.snp_left).offset(-2)
                   make.bottom.equalTo(self.toolBar.snp_bottom).offset(-8)


                })
                sendButton.snp_makeConstraints({ (make) -> Void in
                    make.right.equalTo(self.toolBar.snp_right)
                     make.bottom.equalTo(self.toolBar.snp_bottom).offset(-4.5)

                })

凡匪是圈起简单多矣?我们来解释一下这段代码:
每一个零件都发生一个
snp_makeConstraints的闭包方法,用来装约,textView.snp_makeConstraints即使来安装textView的律
闭包中make.left.equalTo(self.toolBar.snp_left).offset(8)及时行代码可以据此公式来表示:
也就是textView.left = self.toolBar.left + 8,这样平等看便格外直观了,文字框的左距输入框左侧8点。
make.top.equalTo(self.toolBar.snp_top).offset(7.5)好据此公式
textView.top = self.toolBar.top +7.5表示,剩下的代码以此类推,如下图所示:

autoLaout

sendButton的一些吗是这么:
make.right.equalTo(self.toolBar.snp_right)代表发送按钮右侧直接贴输入框的右侧,没有个移
make.bottom.equalTo(self.toolBar.snp_bottom).offset(-4.5)发送按钮底部距离输入框底部4.5碰
这么是匪是让autoLayout变得简单很多矣?后面的类型我们就是一直使用其来进展autoLayout设置了!

图片 2

现尚未错误了,cmd+R运行一下,啊哦,为啥是空手!作者你骗人!( ⊙ o ⊙ )

=好吧,我们还不同一步,记得吗,它而改成第一响应者才能够弹出键盘哦,我们只要再次写一个术它才能够见效!在视图控制器类中多以下方法:

   override func canBecomeFirstResponder() -> Bool {
        return true
    }

告知我们的体系我们打定义的输入框可以改为第一响应者,我们啊是生身份证的!
接下来于运作一下,如果无不当,应该会有以下职能:

chat.gif

忽视黑洞洞的背景,因为咱们尚无添加内容。。。
而是若晤面发现一个问题,键盘怎么回呀。。不管怎么点都无影响啊!

好吧,下面我们来所以一个都行的方法来化解它们。由于聊天页面是一个UITableView,所以我们好采用UITableViewContoller来取代我们的UIViewContoller,这样咱们的页面被便默认有了一个UITableView,然后她发一个雅实用的特性—keyboardDismissMode,我们将她装也.Interactive啊不怕是键盘的弹奏有和撤回状态好依据你针对tableView的拖拽进行更改,也便是公的手指拖到哪里你的键盘就是交哪,是无是异常死。
变动视图控制器的路:

class ChatViewController:UITableViewController,UITextViewDelegate {
....
....
....
}

每当viewDidLoad里添加一行代码来安装keyboardDismissMode:

tableView.keyboardDismissMode = .Interactive

重复运行,你晤面发现黑的背景不见了,取而代之的凡空的TableView!而且键盘也兑现了炫酷的效应!

chat.gif

文章以有的源代码
吓之,第三片万事如意贯彻!第二片段凡咱的中心,内容比较多,所以我将她放到教程的亚有中。
老二局部学科已经出炉,欢迎围观!
swift实现一个同智能机器人聊天的app(二)

若果该文章对你生出协助,请点一下欢喜!您的支持是本身连续写之动力!