出记事本实战,体验perfect框架用swift写服务端

九公主正同丫鬟翠菊在大幅度的园林里赶上打闹时,只见其母亲在它的大姐来吃她了,她不知什么事,只得跟着大姐特别至了天宫琼楼边的画阁里,作为天猫一开销,一寒是只能停止在此间的。

Perfect

至了阁子里,她妈妈跟翁刚刚兴味盎然地游说在啊时,一抬头见了它,忙招手让它过去。她忙伏到娘的怀里,母亲容易抚地抚摸着其,宠溺地问她刚还交何处去矣,她说在园里打着了。母亲突然看见它右手耳朵齐的耳环不见了,忙问其:“幺儿,耳环呢?”

说明

本文Demo是使用 Swift3.0
基给perfect框架用swift写服务端的文章。对于perfect框架入门与安排方面未做了多的授课,想使打听该地方的大佬们请参考以下学习资料,而客户端方面则应用RxSwift框架来描写,关于客户端的情在发出机遇再度展开介绍,本文着重讲解服务端Demo。


幺儿是慈母对作为九尾猫的九公主的昵称,因为它最好小嘛,母亲莫喝其幺儿喊谁为幺儿呢?她的八独姐姐虽然对这有些嫉妒,但他们当作姐姐又十分痛好她,遂笑着给它对说:“肯定在苑里走丢了。”她们说着混乱使把好的耳环拿给小妹戴。

第一献上本文Demo

母亲对这很是欣慰,手一样致,八独姐姐吗到了它们身边,受到了妈妈的抚爱。以后,九公主就是事隔多年,也经常会想起她跟姐姐们于妈妈身边的欢欣的观。

GitHub:服务端Demo(Perfect)

妈妈随即告诉其说其已经满十八年份了,昨天尚做了成人礼,刚刚玉帝已颁下玉旨,让她交凡间去历劫一番,然后回天庭飞起成仙,不仅和八个姐姐一样享有闭月羞花的美妙,而且还和姐姐们平位列仙班。

GitHub:客户端Demo(RxSwift+Moya)

九公主听到这信息后,并无是绝喜欢的,她一样管搂住母亲的脖子说:“可是我弗思量离开妈妈!”她底八只姐姐特别是感动,她们心想难怪母亲爱小妹妹,敢情是小妹妹表面上特别淘气,其实它们十分懂事的,小小的岁数就了解承欢于妈的继承者,让丁不禁顿生万分同病相怜与庇佑的内容。

随后又献上参照的上学资料

妈妈啊是于心不忍,母亲及父亲针对视一眼后,对其说:“娘亲也不忍让您走起来,但‘天上方七日,世上就千年’,你生到下界也从未多长时间就回去了,吾儿忽如难受!”在娘及爸爸的一再规劝下,九公主才应了。

GitHub地址,过万的start

相隔不多长时间,两个金甲神人拉于九公主就倒,到了送是桥上,他们恰好想管九公主往生摒弃去时,太白金星赶来,要九公主喝下忘却汤。这种汤一喝下,九公主下界投胎时便会见忘记所有,她不怕未可知泄漏天机了。

合法中文文档,教练我若学是

可,九公主一心想方父母和八单姐姐,她就是不情愿喝下忘却汤。于是,太白金星只好启禀玉帝,说是九公主不喝忘却汤。玉皇大帝虽未曾玉颜震怒,但心啊是勿乐意之,心里说空的事体岂能让你说之。

perfect框架入门比较不利文章,配置方面称得生详细

玉帝的念还无说说话,九公主已经摆称了,她说:“天父大人息怒,孩儿斗胆也未会见说发生天上的私房的。”玉帝见九公主冰雪聪明,心里怒气稍减了若干,他拘留向王母娘娘。

正文实战Demo主要的参阅来源,对合法文档有有最主要之补说明,入门讲解很详细

王母娘娘会过全来,对九公主挥了指挥袍袖,九公主当时吗从不以为有啊好,她纵然叫简单单金甲神人又牵涉到了送凡桥。到了送凡桥,他们将九公主举起来甩向了人间红尘。

Perfect是呀东西呢?

Perfect是均等组完整、强大的工具箱、软件框架体系暨Web应用服务器,可以于Linux、iOS和macOS (OS X)上运。该软件体系也Swift工程师量身定制了套用来开发轻量、易维护、规模可扩大的Web应用与另REST服务之解决方案,这样Swift工程师就得实现以以服务器和客户端上使用相同种植语言开发软件项目。

九公主悠悠荡荡,恍若到了长安城郊乡下一个土豪老爷的婆姨。这个土豪姓金名天赐,金员外娶有一样各妻子和三房姨太太。这些年,不管金员外怎样辛勤耕耘,勤奋播种,他的内跟三房姨太太的胃就不见一点动静。

性能比

性能比

如出一辙篇性能比的文章:无适应跑个分叉


无独有偶当金员外想再娶一房姨太太时,那年情上,三姨太的胃隆起来了,金员外酷喜欢,忙将三姨太移动到好的堂屋中,他就是与三姨太分床睡觉,但他亲自照料三姨太的伙食生活,是外肯的,况且他每次抚摸三姨太日渐鼓起的肚子,他老是慌有成就感。

关于是什么由让自己想上学perfect呢?

当同样名叫刚接触ios开发尚未多久的小白,回忆起当年入学校一个软件开发团队的早晚,为了能够及集团旁方面的口相互协作,了解任何地方的有基本知识是来必要的。就哼于前后端交互,作为活动端方面也使了解后端知识,这样在上下端交互的时段就是会见少多琐事。于是当加盟团队初期,师兄便要求自要好写一个demo,服务端你用啊形容都得以。对于当下底我来说,真的是项麻烦事了,因为学习ios并无像上学Android,Android使用java语言,Android与java服务器相互协作,所以当求学Android的以还是多还是掉为会套到有些后端的文化。樂虽然最后自己用python写了一个要命烂的后端,但是那时候就在怀念啊甚非可知写Android那样,能就此平等种植语言为描绘后端。直到前数日子发现了perfect,倍感欢喜,于是就琢磨了同样胡。


阳春怀胎,一为分娩。三姨太怀孕十月后,瓜熟将蒂落,无奈三姨太羊水早就散了,宫孔为曾开始好几日了,孩子就是不情愿降临人世。

属下去实战Demo! GO! GO! GO!

刚巧当全家人揪心焦急时,三姨太所居住之房舍里,哇的均等望,一个婴儿的啼叫划破了世界。金员外仿佛在黎明前之黑暗中看见了巴之晨光似的,他忙于向三姨太那儿奔去,不多同会晤,他的妻子金夫人呢来了。

第一片段:Demo演示

出于简书限制了图的尺寸,所以只能分开进行现身说法。(内心的忧愁你们该清楚吧)

稳产婆于她们报喜,说是生了一个娇艳的小姐,金员外与金夫人十分喜,忙赏赏了稳产婆。他们走上前房间里,三姨太疲惫不堪地躺在当场,但怀里还是赢得在小姐,并拿被盖得紧。

注册:

金员外及金夫人见了,十分心疼,忙给人口端来鸡汤,金夫人亲自为三姨太嗨食着。她把三姨太抱在臂弯里,不鸣金收兵地哄三姨太喝汤,说是不喝是绝非奶的。

登录:

果不其然,三姨太后来奶水很丰盛,这都得益于钱夫人熬煮的鸡汤。小姐长得粉嘟嘟的,人见人爱。三年晚,三姨太又生下一个男婴。

累加记:

为了三姨太一心一意哺乳公子,金夫人将小姐获到它作里招呼起来,她叫小姐从名叫金鸣凤,还让金鸣凤小姐喊她为娘。但金鸣凤只对它们点点头,就是无喊她吃一声娘。

改笔记:

开始,金夫人也远非当完全,但其相当来当错过,就是没有能顶交资小姐喊她一声娘,她发出把怪了,忙在人口去喊金员外。金员外来了后,也充分急,忙找郎中医生给金钱小姐治疗。金小姐的哑疾是天然带来的,岂会说治疗就医疗的。这样直白到资小姐十八春秋时,仍然没有人看好金小姐的哑疾。

去笔记:

可是金员外与金夫人从不轻言放弃,他们在皇城前后贴上了广告,广而告之,如果谁能够看好金小姐的哑疾,年老的赏赐白银千两,年轻未婚的把金小姐许配于他举行家。

数据库中一直操作:

重赏之下必有勇夫,一时间来让金钱小姐治疗哑疾的要过江之鲫,但尚无一人发何良方治好金小姐的病。金员外与金夫人心烦死了,三姨太为落在金小姐哭喊在:“吾儿怎么会这样命苦啊!”金小姐十分智慧,她于在手势和老人家说不要紧的,她底致病没有人看得好,是盖它自娘胎里即使带来上之。金员外和金夫人以及三姨太听了后,心都散了。

仲部分:初始化项目结构

先是给我们仍的完成初始化工作,我们的工称为就受iNoteServer好了,所以我们创建一个iNoteServer,在iNoteServer里我们使用终端创建Package.swfit文件和一个Sources文件夹,在Sources文件夹里创建一个main.swift文件。你的档次结构在iNoteServer文件里看起是这般的:

紧接着在Package.swfit文件被,写副待用的库。

import PackageDescription

let versions = Version(0,0,0)..<Version(10,0,0)
let urls = [
    "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", //服务端核心框架
    "https://github.com/SwiftORM/MySQL-StORM.git", //对象关系型数据库
]

let package = Package(
    name: "iNoteServer",
    targets: [],
    dependencies: urls.map { .Package(url: $0, versions: versions) }
)

然后我们以终端中输入swift
build。(该过程等的年月挺久的,毕竟网速慢,文件为非小…)

fetch完成以后,输入swift package
generate-xcodeproj命令创建iNoteServer.xcodeproj文件。打开iNoteServer.xcodeproj文件,在Build
Settings中Library Search Paths检索项目软件库中益(不单单是编译目标)

$(PROJECT_DIR) - Recursive

说到底,我们分开一下目:

DataBase目录里存含管理数据库的接近(DatabaseManager),一些ORM对象的数据模型(User对象,NoteContent对象)
NetworkServer目录里存放接口API(iNoteAIP)以及HTTPServer类(NetworkServerManager)
于是当main文件被,我们如果简单的经过HTTPServer类来调用start方法就得直接开行服务器了

NetworkServerManager.share.serverStart()

至今,我们种之初始化已经完成了,可喜可贺,可喜可贺。


便以合家跌入清的绝境中时,金家宅门外来了一个青年公子,有如玉树临风一般,潇洒的极,卓尔不凡,跟金小姐的沉鱼落雁之容闭月羞花之貌是有得一样拼的。如果他跟金小姐站一堆儿,保不准金小姐都见面当他与其是天生的一样针对性地造的一律对。

老三局部:创建各功能模块的接口

以此,我创建一个iNoteAPI文件用来管理各模块的接口

enum iNoteAIP: String {
    case base = "/iNote"            
    case register = "/register"         //注册页面
    case login = "/login"               //登录页面
    case contentList = "/contentList"   //获取笔记列表
    case addNote = "/addNote"           //添加笔记
    case deleteNote = "/deleteNote"     //删除笔记
    case modifyNote = "/modifyNote"     //修改笔记
}

妙龄公子被门房引到大厅及,此时金小姐正依偎在金夫人怀里撒在宠幸呢,她一抬头就与青年公子眼碰上了,她醒来眼前一亮,她当就口最可爱了,心弦不觉颤动了一晃。但由千金小姐的拘谨羞涩,她吗从未好活动上前主动与他表白,就是想和人家表白也并未因此,她无会见称啊,她比也只有发生家里人知道,外人怎么懂得她底哑语和身体语言!

季总统:创建HTTP服务器管理类

在此之前我或者事先领一下使用perfect框架构建服务器的着力流程,详细的抑请圈读参考资料。
以main文件被直接写副以下代码:

import PerfectLib
import PerfectHTTP
import PerfectHTTPServer

// 创建HTTP服务器
let server = HTTPServer()
// 监听8181端口
server.serverPort = 8181
//创建路由组,用来存放各个路由
var routes = Routes()
//注册您自己的路由和请求/响应句柄 (请求方法,地址,请求处理)
routes.add(method: .get, uri: "test") { (request, response) in
    response.setBody(string: "hello word!")
    response.completed()
}
// 将路由注册到服务器上
server.addRoutes(routes)
// 启动服务器
do {
    try server.start()
} catch PerfectError.networkError(let code, let msg) {
    print("network error:\(code) \(msg)")
} catch {
    print("unknow network error: \(error)")
}

command⌘ + R 跑起来~~~🏃

紧接着打开浏览器,输入localhost:8181/test,一按部就班回车

成的示响应句柄,我们的服务器成功之走起了,可喜可贺,可喜可贺。
即时就是是无与伦比核心的构建流程。

回本文的Demo中,我们以main文件被,只是简短的经过startServer艺术启动服务器,因此我们创建NetworkServerManager类似来封装以上之流程。

class NetworkServerManager {
    // 创建HTTP服务器
    let server = HTTPServer()
    //创建路由组,用来存放路由
    var routes = Routes(baseUri: iNoteAIP.base.rawValue)

    static let share = NetworkServerManager()
    private init() {
        //注册您自己的路由和请求/响应句柄 (请求方法,地址,请求处理)
        configure()
    }

    func serverStart(_ port: UInt16 = 8181) {
        // 监听8181端口
        server.serverPort = port
        // 将路由注册到服务器上
        server.addRoutes(routes)
        // 启动服务器
        do {
            try server.start()
        } catch PerfectError.networkError(let code, let msg) {
            print("network error:\(code) \(msg)")
        } catch {
            print("unknow network error: \(error)")
        }
    }

    //uri使用iNoteAIP中的枚举值字符串
    func addRouteWith(method: HTTPMethod, uri: iNoteAIP, handler: @escaping RequestHandler) {
        routes.add(method: method, uri: uri.rawValue, handler: handler)
    }
}

咱们于初始化单例时,通过调用configure方法以各国接口的之路由于上加于程由于组中,handler参数传的凡各接口的句子柄处理,返回RequestHandler类型。

extension NetworkServerManager {
    //添加各模块的路由
    func configure() {
        //登录注册接口的路由
        addRouteWith(method: .post, uri: .register, handler: userRegisterHandle())
        addRouteWith(method: .post, uri: .login, handler: userLoginHandle())
        //笔记的CURD接口的路由
        addRouteWith(method: .get, uri: .contentList, handler: getNoteContentListHandle())
        addRouteWith(method: .post, uri: .addNote, handler: addNoteHandel())
        addRouteWith(method: .delete, uri: .deleteNote, handler: deleteNoteHandle())
        addRouteWith(method: .post, uri: .modifyNote, handler: modifyNoteHandle())
    }
}

叫咱们来探视RequestHandler是呀品种

public typealias RequestHandler = (HTTPRequest, HTTPResponse) -> ()

原是一个闭包嘛,如果我们于configure中因故闭包形式写handler,那会更换得臃肿。因此我们好透过函数来回到该闭包。

// MARK:- 注册和登录
extension NetworkServerManager {
    func userRegisterHandle() -> RequestHandler {
        return {[weak self] request, response in
           //TODO: 处理注册请求
        }
    }
    func userLoginHandle() -> RequestHandler {
        return {[weak self] request, response in
            //TODO: 处理登录请求
        }
    }
}

// MARK:- 笔记CURD
extension NetworkServerManager {
    func getNoteContentListHandle() -> RequestHandler {
        return {[weak self] request, response in
            //TODO: 处理获取笔记列表请求
        }
    }
    func addNoteHandel() -> RequestHandler {
        return {[weak self] request, response in
            //TODO: 处理添加笔记请求
        }
    }
    func deleteNoteHandle() -> RequestHandler {
        return {[weak self] request, response in
            //TODO: 处理删除笔记请求
        }
    }
    func modifyNoteHandle() -> RequestHandler {
        return {[weak self] request, response in
            //TODO: 处理修改笔记请求
        }
    }
}

然,我们就算可以当main文件被经过简单的调用启动服务器了,并以个艺术吃拍卖相应的客户端请求,可喜可贺,可喜可贺。


妙龄公子自称姓姜,叫姜伯儒,他是一个举子,是交长安首都来赶考的。不过,他到长安晚意识身上银子没有了,是为人盗取了吧,还是少了啊,就未知晓了。总之,他没有银子了,正在他上天无路入地无门时,他看看了街头的广告,他当这正是天无绝人之路,上天为他送银子来了。他说:“我能够治好小姐的病倒,我家有平等栽秘方,一定能够治病好小姐的病倒。”

第五组成部分:定制而赶回的json格式

此刻,我们少还先歇下来想有题材,例如处理一个客户端的乞求我们理应举行些什么工作啊?客户端传过来的参数缺少必要的字段时我们该归什么消息?正确时我们而该归什么消息?错误信息和成功之信息格式是哪些的?又是否大致相同?
于是乎自己就算以同一种植最简单易行的格式来进行现身说法(反正是现身说法嘛,将就一下),json格式看起像是这样的:

{
  "status": "SUCCESS",
  "data": [],
  "message": "注册成功",
  "result": true
}

{
  "status": "FAILURE",
  "data": [],
  "message": "缺少对应参数",
  "result": false
}

data中之数量根据对应的接口来构建。所以我们刻画一个朵举值来回到status状态,写一个函数用来处理生成该json格式的字典。

// MARK:- status状态
enum ResponseStatus: String {
    case success = "SUCCESS"
    case failure = "FAILURE"
}

extension NetworkServerManager {
    // 处理要返回的响应体,构建json格式
    func requestHandle(request: HTTPRequest, response: HTTPResponse, status: ResponseStatus, result: Bool, resultMessage: String, data:[[String:Any]]?) {
        let jsonDic: [String:Any]
        jsonDic = [
            "status":status.rawValue,
            "result": result,
             "message":resultMessage,
             "data":data ?? []
        ]
        do {
        //jsonEncodedString: 对字典的扩展方法,返回对应json格式的字符串
            let json = try jsonDic.jsonEncodedString() 
            response.setBody(string: json)
        } catch {
            print(error)
        }
        response.completed()
    }
}

json格式已经来矣,紧接着我们而针对性客户端请求的参数表格中取出必要的参数进行官方判断。以登记为例:

func userLoginHandle() -> RequestHandler {
        return {[weak self] request, response in
            guard let phoneNum =  request.param(name: "phoneNum"),
                  let password = request.param(name: "password"),
                  phoneNum.characters.count > 0,
                  password.characters.count > 0
            else {
                self?.requestHandle(request: request, response: response, status: .failure, result: false, resultMessage: "缺少对应参数", data: nil)
                return
            }

             //TODO: 参数合法则进行数据库对应操作

        }
}

旁的接口获取参数后的拍卖啊跟注册相似,至此,我们的NetworkServerManager看似在逻辑上着力好了,接下要做的从业是同数据库打交道了,我们于DataBase文件夹着开创数据库管理类来呢咱开展处理多少,毕竟我们不容许于劳动器类写数据库对吧…


他说这种秘方虽未曾什么奇怪之处,但吃醋煞叫做医气死神仙是不必置疑的。于是,他当金家住了下来,他上山去采访来了他待之中草药,并于小姐熬煮药汤了。他经受好药汤后心惊胆战钱夫人起疑,还友善喝了同人口,一点无碍事,而且他讲的鸣响再次坦承更显示了。

第六片:数据库

如今,我们当DataBase文件夹着创造DatabaseManager类来治本数据库,这里我们采用得是ORM数据库,同样我们用单例来展开调用。在初始化配置时我们对MySQLConnector进行布局(密码记得填你们自己之),这里我们连寻找不顶接近start的计来启动数据库连接,因为她会于当的下就自动建立连接,例如调用单例的时段,因此我们不必担心建立连接、关闭连接、打开数据库、关闭数据库等。

数据库的布局根据自己之信进行相应的布置。

// MARK:- 数据库管理类
class DatabaseManager {
    static let share = DatabaseManager()
    private init() {
        MySQLConnector.host = "127.0.0.1" 
        MySQLConnector.username = "root"
        MySQLConnector.password = "此处填你自己的mysql密码"
        MySQLConnector.database = "iNote" //MySql中创建的iNote数据库
        MySQLConnector.port = 3306
    }
}

既是ORM数据库,我们虽不需要写给丁乱的sql语句,而是大概的经过调用对象的措施开展数据库的操作,以报到为条例:

// MARK:- User
extension DatabaseManager {
    // 返回登录操作后的结果(result, message, userInfo)
    func loginWith(phoneNum: String, password: String) -> (Bool, String, [String:String]) {
        return User.userLoginWith(phone: phoneNum, pwd: password) // <-- TODO:
    }
}

以外表的NetworkServerManager恍如吃我们便可调用DatabaseManager了,以报到为条例:

func userLoginHandle() -> RequestHandler {
        return {[weak self] request, response in
            guard let phoneNum =  request.param(name: "phoneNum"),
                  let password = request.param(name: "password"),
                  phoneNum.characters.count > 0,
                  password.characters.count > 0
            else {
                self?.requestHandle(request: request, response: response, status: .failure, result: false, resultMessage: "缺少对应参数", data: nil)
                return
            }
            // 操作是否成功, 结果信息, 用户信息
            let (result, msg, info) = DatabaseManager.share.loginWith(phoneNum: phoneNum, password: password)
            let status: ResponseStatus = result ? .success : .failure
            self?.requestHandle(request: request, response: response, status: status, result: result, resultMessage: msg, data: [info])
    }
}

其他接口的拍卖及之类似,可以翻本文的劳务端Demo,现在我们延续为报到为例,接下去的政工仅仅剩余User仿佛对数据库的操作了。成功接近于近,可喜可贺,可喜可贺。


金夫人大喜过望,忙接了药碗亲自用汤匙舀着叫金钱小姐喂喝在,她一面叫金小姐喝还单说:“吾儿起名喝下姜举人的药汤,就可知谈了。听话啊,乖乖的!”此情此景,把金员外与三姨太为打动得热汨盈眶,他们看金夫人把金钱小姐看得比她好亲生的幼女还要亲自,实在是宝贵的。

第七有:MySQLStORM对象

应用ORM数据库实际上是操作ORM对象,perfect框架已拉咱落实所急需的CURD方法,我们直接调用方法的主意来操作数据库即可。我们仅需要写对应之范类,继承MySQLStORM类似,实现要求重新写的父类方法即可。该型对应之属性名、属性类型便是数据库被对应之字段名与字段类型。这里引入官方文档的一个生死攸关要求:

️注意️ 该目标的率先单特性将改为对应数据表的主索引 ——
传统的法门就是是为主索引列起名叫做
id,虽然您得吧主索引字段设置任何有效之名字。SQL这种关系数据库的主索引典型项目是整型、字符串或者UUID编码。如果您的主索引不是自动递增的平头,则势必要设置好者id值,以保证数据的完整性和一致性。

坐处理用户注册登录的User模型为条例(这里只是为了简单演示为没弄UUID、token之类的字段):

import Foundation
import MySQLStORM
import StORM

class User: MySQLStORM {
    // ️注意️:第一个属性将成为主索引字段,所以应该是ID
    var id: Int = 0
    var phoneNum: String = ""
    var password: String = ""
    var registerTime: String = ""

    fileprivate override init() {
        super.init()
        do {
            //确保该模型的表格存在
            try setupTable()
        } catch {
            print(error)
        }
    }

    //给对象的表名
    override func table() -> String {
        return "User"
    }

    override func to(_ this: StORMRow) {
        id = numericCast(this.data["id"] as! Int32)
        phoneNum = this.data["phoneNum"] as! String
        password = this.data["password"] as! String
        registerTime = this.data["registerTime"] as! String
    }

    fileprivate func rows() -> [User] {
        var rows: [User] = []
        for r in results.rows {
            let row = User()
            row.to(r)
            rows.append(row)
        }
        return rows
    }
}

在此间根本说明一下于to方法被为何以numericCastnumericCast大凡用以整型之间的变的,在实战的过程中,起初直接用this.data["id"] as! Int是尚未问题,可是当起数据库被读取数据时虽报了一个破绽百出。

Could not cast value of type 'Swift.Int32' (0x1014c1df0) to 'Swift.Int' (0x1014c2430).
2017-11-03 20:50:23.014244+0800 iNoteServer[54873:750541] Could not cast value of type 'Swift.Int32' (0x1014c1df0) to 'Swift.Int' (0x1014c2430).

从数据库读取出来的id类型变成了Int32了。(当时我脸就是是这么黑的),所以用numericCast来换一下项目即可。

//API相关操作
extension User {
    //验证用户是否存在
    fileprivate func findUserWith(_ phone: String) {
        // fine: 如果在数据库中匹配到了,则将字段的内容赋值给对象中的属性,否则什么都不做
        do {
            try find([("phoneNum",phone)])
        } catch {
            print(error)
        }
    }

    //登录 -> 返回(操作结果, 结果信息, 用户信息)
    static func userLoginWith(phone: String, pwd: String) -> (Bool, String, [String:String]) {
        let user = User()
        user.findUserWith(phone)
        if user.phoneNum == phone && user.password == pwd {
            let info = [
                            "userId": "\(user.id)",
                            "phoneNum": user.phoneNum,
                            "registerTime": user.registerTime
                        ]
            return (true, "登录成功", info)
        } else {
            let info = ["userId": "", "phoneNum": "", "registerTime": ""]
            return (false, "用户名或密码错误", info)
        }
    }
}

时至今日,用户登录功能就主导好了。现在交了测试接口的时候了,成败以这个一举。**command⌘

  • R 跑起来~~~~🏃**。在这里我们采用Paw(测接口的神器)来测试我们的接口:

金鸣凤小姐喝下姜举人的药汤后,当真正千年的苏铁开了消费,聋哑人沉寂了十八年今日讲话讲了言语。她先是望就喊金夫人为娘,又喊金员外为爹,还相继喊了大妈和二娘以及三娘,喊三娘时,她前进抱了抱生她留它底娘亲。金家上下高兴死,马上张灯结彩,择日不使遇上日地被姜举人和金小姐举行了严肃的繁华的婚礼。

成功了~~

旁接口的实现方式也按同样的老路实现即足以,至此,本文基于perfect框架用swift写服务端也在此地已。接下来则会刻画一篇与这个iNoteServer服务端相对应的iNoteClient。
关于自己才疏学浅,对后端只是知情,斗胆尝试,如果错漏,恳请各位老佬多多包涵与明示。藍

姜金二人数婚后近无比如胶似漆,如鱼得水难解难分。姜伯儒以夜幕习课业准备往考时,金鸣凤小姐为当干也外“红袖添香夜读书”。后来,姜伯儒去考试了,可是也传播了不好的音讯。

说是姜伯儒的卷子里来“明月不识字,何故照书卷”的诗,明明皇帝便受唐明皇,他尚如此写,明明虽是相反朝嘛,这尚了得!他不只没赢得功名,反而被打入天牢,只待秋后某个同上午时三刻斩首示众。

消息传开,合府慌张,金鸣凤小姐一急,竟然两眼一闭,她充分了。金家上下哭成一团,但为从没办法呀,只得将钱小姐停灵在堂屋里,只相当三日晚安葬。

再说金小姐的魂魄荡荡悠悠地直向天庭而去,一路直达,黑白无常也无敢拦阻。她到了天庭上后,太白金星亲自来迎接她,并拿她带来顶金銮殿上,玉皇大帝敕封她吗九仙姑,并给其同它们底老人和姐姐们住到联合。

而是九仙姑此时纪念着它底女婿姜伯儒,见到家中老小后也是抑郁。她推说要交园林里溜达到一下,她起了画阁就顶了送凡桥,她背着了近桥官从桥上超过了下来。她底仙魂烈魄一下子暨了金员外家,看到好的遗体,她嗖地一下就扑了上去,她还要活转过来了。

金鸣凤小姐活转过来了,金家上下高兴得杀,金夫人还亲自来确认,她说:“丫头,你绝不吓娘,你尽管不是自个儿亲生,但自我看看若要是我有,你比较自己的亲生女儿还要亲自!”金鸣凤说:“娘,看君说的,人家只不过是头昏过去了,哪里就挺了呢!”她说在,还伸手去拉金家的手,金夫人觉得她底手温暖而春,她喜极而泣,一管获得住金小姐说:“儿呦,你唯独把娘疼死了!”

金钱小姐死而复生,她首先码使召开的事就是营救出陷在天牢中之丈夫姜伯儒。她运起轻功,到了天牢里,把看牢的牢头用手一样指,牢头就倒地呼呼大睡了,她趁着把钥匙取出打开了羁押姜伯儒的牢房,然后用一障眼法把同彻底木棍变成了姜伯儒蹲在牢狱中后,她不怕带在姜伯儒安然无恙地运动来了牢房。

金钱小姐带在姜伯儒回家后,金家家人还晓得了,除了几只亲人知道姜伯儒是钦犯外,其余的还以为姜伯儒是产生了平等回家回来了。不过,为了怕走漏风声,金小姐还是将姜伯儒藏于绣楼里,夫妻二总人口十分少出走动。

顶秋后问斩晚,姜伯儒才成逃脱,这吗是金钱小姐无思量就此重新多之灵力才有结果,如果它滥施灵力的话,姜伯儒早就非去牢狱之灾了。但是,就是如此,金小姐还是触犯了天条,玉帝派一强暴之巨灵神到钱财小姐家,当众把钱小姐一掌握面去灵力仙气,金小姐迅速成一单纯普通的凡猫。她喵喵地被着,样子确实很,金夫人将她赢得在怀中,热泪滚滚而下。

姜伯儒眼睁睁地圈正在金钱小姐变为一但猫儿,他看罢有灵异故事,他猜测这不是一般的猫,她早晚是天上的神猫下界历劫的,她无拖欠用她底灵力救了他,她是针对他动了真情才会生出如此下场的哟。他从金夫人手中获取回那只有猫,那只是猫为真正想不到,姜伯儒来博取其经常,她竟然倏地就超到姜伯儒手中了,她底泪珠打湿了姜伯儒的手。

姜伯儒仰天长啸,他说:“苍天啊,都说好人口闹好报,可是我的内这么好之丁,你可施法让其变成了猫,你作苍天,你作青天大老爷,你最不公正啊!苍天啊,你切莫配称为上!”金府里的人口听到姜伯儒的哭诉,都嚎啕大哭,哭声震天。

下界发生的这些业务,在额头上的玉皇大帝和王母娘娘都是亮之,但她们也装在无瞧见,姜伯儒的哭诉和金府的怨气冲天,他们吗装作在没听见,他们照喝他们之玉液琼浆,他们还是餐英咀华。他们无动于衷,充耳不闻,熟视无睹。

不过,金小姐在下界的事务与金府里之人之哭诉,九仙姑的老人家及八单姐姐也视了与听到了,她们也九仙姑的凄惨的面临而感觉到撕心裂肺,她们想起俏皮可爱的九仙姑变成了人间的一律独猫,心疼得不可了。

九仙姑的八个姐姐不等父母说,她们就算挪有了画阁,她们到了送是桥及嗖地一下便跳荡到了凡界,她们脚踏五彩祥云,一直到了金府降落下。

他俩从姜伯儒时接了猫儿,然后把猫儿放到地上,她们围在猫儿坐成一圈,然后伸出她们的秀掌,一齐向猫身上不绝如缕地输送着一波并且平等波的灵力仙气。她们的额头上汩汩地流下了黄豆大之汗水,她们的头顶起起起雾霭似的热浪。

过了有稍许半上之年月,地上的猫儿又成为了钱财小姐的眉宇,她走向八只姐姐。她说:“姐姐们,谢谢你们!”大姐说:“小妹,不要谢,我们不得不帮你变成人,但变成不了神了。”

金钱小姐说:“但愿人间真情在,只羡鸳鸯不羡仙!”八独姐姐深表同感,她们说这次他们吗得罪了天条,估计天上也不会见容下她们了,过无多久,她们虽见面来和妹妹一起当凡变作普普通通的阿斗。她们说正在,就辞了钱财小姐与金府里之丁,又驾驶着五彩祥云向天飞越而去。

起名 1

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图