从刚刚入门IOS不久,就有一种自己开发app的冲动。但是发现一个现实又无奈的问题,没有后台啊,自己有不会弄。这篇文章是我这两个星期的努力,我觉得自己文笔太差,写不清楚的地方大家直接问我就好。
一般APP都需要前端和后台。作为一个IOS开发,前端可以自己搞定,但是后台就没办法了。想学习一下java,PHP什么的有没有入门的地方。今天我就介绍一下我用过的两个方法来实现一下服务器的功能。
第一个是在小波的视频里学习到的。使用MAMP和wordpress。来实现这个我推荐大家看小波视频吧。
毕竟视频总比文字来的直接,而且大神是专业的。
本来我用这个组合用的挺好。后来我有个要维护用户的需求怎么弄也没找到解决的办法。一顿纠结后就到了我们下面要说的perfect了。
perfect是一款基于swift的服务器框架,也有了两年了吧。记得好早以前我就见过了,但是之前一直没成功过,这回翻出来一看。官网有了中文文档。网上也有了不少的教程了。
既然开发那么官网一定要看的。这里先说一个坑。文档上开头说的要求swift3.0.这个事,可能是文档太久没更新了。现在是可以使用swift4的。我特意用3.0反而一直失败。坑爹。。。
开篇先说一下我现在的环境是Xcode9.0。
第一步初始化项目
1.打开终端,新建一个PerfectDemoProject文件夹用于保存项目文件。
mkdir PerfectDemoProject
cd PerfectDemoProject
2.初始化git----(这里没安装git的可以安装一下)
git init
touch README.html
git add README.html
git commit -m "Initial commit"
3.创建Package.swift文件 -- 这个是一会编译必要的文字,这里要写上你要用的软件包
touch Package.swift ----创建文件
打开文件编辑
//软件包管理
import PackageDescription
let urls = [
"https://github.com/PerfectlySoft/Perfect-HTTPServer.git", //HTTP服务
"https://github.com/PerfectlySoft/Perfect-MySQL.git", //MySQL服务
"https://github.com/PerfectlySoft/Perfect-Mustache.git" //Mustache
]
let package = Package(
name: "PerfectDemoProject",
targets: [],
dependencies: urls.map { .Package(url: $0, versions: Version(3,0,0)..<Version(4,0,0)) }
)
这里这个Version的写法有好多种,,亲测这种最靠谱其他的多少都有点问题。。。。
4.创建Sources文件夹 ---这里主要是放我们的代码。先放一个Hello World。嘿嘿
mkdir Sources
echo 'print("Hello World!")' >> Sources/main.swift
5.编译 --- 这部分很容易出错。而且有的时候网络不好也会报错。错了请默念老天保佑然后多试几次
swift build
6.运行,成功控制台会输出Hello World --- 如果你过了上一步。那恭喜你下面没多大问题。额至少这一段
.build/debug/PerfectDemoProject
第二步放到Xcode
第一大部分我们解决了,接下了我们把这个项目放到我们熟悉的Xcode上
1.创建成Xcode可以运行项目
swift package generate-xcodeproj
2.在让我们打开项目看看,应该有了PerfectDemoProject.xcodeproj。用Xcode打开它
在Build Settings中Library Search Paths检索项目软件库中增加$(PROJECT_DIR)
3.编译一下
应该没啥问题若果出错了回到1.创建成Xcode可以运行项目再来一遍
第三步开始写服务器
1。创建并编辑NetworkServerManager.swift
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
open class NetworkServerManager {
fileprivate var server: HTTPServer
internal init(root: String, port: UInt16) {
server = HTTPServer.init() //创建HTTPServer服务器
var routes = Routes.init(baseUri: "/api") //创建路由器
configure(routes: &routes) //注册路由
server.addRoutes(routes) //路由添加进服务
server.serverPort = port //端口
server.documentRoot = root //根目录
server.setResponseFilters([(Filter404(), .high)]) //404过滤
}
//MARK: 开启服务
open func startServer() {
do {
print("启动HTTP服务器")
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("网络出现错误:\(err) \(msg)")
} catch {
print("网络未知错误")
}
}
//MARK: 注册路由
fileprivate func configure(routes: inout Routes) {
// 添加接口,请求方式,路径
routes.add(method: .get, uri: "/") { (request, response) in
response.setHeader( .contentType, value: "text/html") //响应头
let jsonDic = ["hello": "world"]
let jsonString = self.baseResponseBodyJSONData(status: 200, message: "成功", data: jsonDic)
response.setBody(string: jsonString) //响应体
response.completed() //响应
}
}
//MARK: 通用响应格式
func baseResponseBodyJSONData(status: Int, message: String, data: Any!) -> String {
var result = Dictionary<String, Any>()
result.updateValue(status, forKey: "status")
result.updateValue(message, forKey: "message")
if (data != nil) {
result.updateValue(data, forKey: "data")
}else{
result.updateValue("", forKey: "data")
}
guard let jsonString = try? result.jsonEncodedString() else {
return ""
}
return jsonString
}
//MARK: 404过滤
struct Filter404: HTTPResponseFilter {
func filterBody(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) {
callback(.continue)
}
func filterHeaders(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) {
if case .notFound = response.status {
response.setBody(string: "404 文件\(response.request.path)不存在。")
response.setHeader(.contentLength, value: "\(response.bodyBytes.count)")
callback(.done)
} else {
callback(.continue)
}
}
}
}
2。编辑main文件
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
//HTTP服务
let networkServer = NetworkServerManager(root: "webroot", port: 8888)
networkServer.startServer()
3.运行
成功的话,会在log看到输出
第四步连接MySQL
嗯电脑要安装MySQL,我是直接在官网下载安装的,也出过一些问题,这里就不说了。很多坑我也没弄明白。至于数据库编辑软件,我用的是Navicat Premium。用起来简单明了。
1。创建并编辑DataBaseManager.swift
import MySQL
//MARK: 数据库信息
let mysql_host = "127.0.0.1" //地址
let mysql_user = "root"//账号
let mysql_password = "a12345"//密码
let mysql_database = "TestProject"//数据库名字
//MARK: 表信息
let table_account = "TestTable" //表名字
open class DataBaseManager {
fileprivate var mysql: MySQL
internal init() {
mysql = MySQL.init() //创建MySQL对象
guard connectedDataBase() else { //开启MySQL连接
return
}
}
//MARK: 开启连接
private func connectedDataBase() -> Bool {
let connected = mysql.connect(host: mysql_host, user: mysql_user, password: mysql_password, db: mysql_database)
guard connected else {
print("MySQL连接失败" + mysql.errorMessage())
return false
}
print("MySQL连接成功")
return true
}
//MARK: 执行SQL语句
/// 执行SQL语句
///
/// - Parameter sql: sql语句
/// - Returns: 返回元组(success:是否成功 result:结果)
@discardableResult
func mysqlStatement(_ sql: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
guard mysql.selectDatabase(named: mysql_database) else { //指定database
let msg = "未找到\(mysql_database)数据库"
print(msg)
return (false, nil, msg)
}
let successQuery = mysql.query(statement: sql) //sql语句
guard successQuery else {
let msg = "SQL失败: \(sql)"
print(msg)
return (false, nil, msg)
}
let msg = "SQL成功: \(sql)"
print(msg)
return (true, mysql.storeResults(), msg) //sql执行成功
}
/// 增
///
/// - Parameters:
/// - tableName: 表
/// - key: 键 (键,键,键)
/// - value: 值 ('值', '值', '值')
func insertDatabaseSQL(tableName: String, key: String, value: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String){
let SQL = "INSERT INTO \(tableName) (\(key)) VALUES (\(value))"
return mysqlStatement(SQL)
}
/// 删
///
/// - Parameters:
/// - tableName: 表
/// - key: 键
/// - value: 值
func deleteDatabaseSQL(tableName: String, key: String, value: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
let SQL = "DELETE FROM \(tableName) WHERE \(key) = '\(value)'"
return mysqlStatement(SQL)
}
/// 改
///
/// - Parameters:
/// - tableName: 表
/// - keyValue: 键值对( 键='值', 键='值', 键='值' )
/// - whereKey: 查找key
/// - whereValue: 查找value
func updateDatabaseSQL(tableName: String, keyValue: String, whereKey: String, whereValue: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
let SQL = "UPDATE \(tableName) SET \(keyValue) WHERE \(whereKey) = '\(whereValue)'"
return mysqlStatement(SQL)
}
/// 查所有
///
/// - Parameters:
/// - tableName: 表
/// - key: 键
func selectAllDatabaseSQL(tableName: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
let SQL = "SELECT * FROM \(tableName)"
return mysqlStatement(SQL)
}
/// 查
///
/// - Parameters:
/// - tableName: 表
/// - keyValue: 键值对
func selectAllDataBaseSQLwhere(tableName: String, keyValue: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
let SQL = "SELECT * FROM \(tableName) WHERE \(keyValue)"
return mysqlStatement(SQL)
}
//MARK:接口使用的具体方法
//获取account_level表中所有数据
func mysqlGetHomeDataResult() -> [Dictionary<String, String>]? {
let result = selectAllDatabaseSQL(tableName: table_level)
var resultArray = [Dictionary<String, String>]()
var dic = [String:String]()
result.mysqlResult?.forEachRow(callback: { (row) in
dic["accountLevelId"] = row[0]
dic["name"] = row[1]
resultArray.append(dic)
})
return resultArray
}
}
嗯嗯我觉得简简单单的说完了。接下来我祝愿大家多多遇见坑(别打脸)。
那么这些弄完的结果是什么样子呢。只要是同局域网中就能访问你的接口。至于其他网络。我还没解决,初步研究是要把当前电脑注册到公网上。我现在打算用MacOS Server试试(下了软件在升级系统呢?)。如果可以是不是就很赞了。等我消息吧!!!这个地方用的技术叫内网穿透,很多软件可以实现,打架可以百度一下。不难的。
ps:虽说官方文档上有不对的地方,还是非常好,真心研究的话一定要看。加油
网友评论