swift设备管理制作过程(xib自动布局)
该工程git仓库 https://gitee.com/zjf1998/DeviceManage-swift
目录
4.2实现HomeViewController,并使用xib适配 17
2.添加上下左右4个约束0,使得这个tableView布满整个屏幕 24
3.新建一个viewController,同时添加一个webView,同样使其布满整个屏幕 25
4.最后在infoViewController中添加tableViewCell点击事件 25
1.创建ShoppingCartViewController并勾选xib文件 26
2.在xib文件中拖入一个tableView和一个view 27
1. swift工程搭建
1.1新建DeviceManager-swift项目
首先需要使用Xcode创建DeviceManager-swift工程,选择iOS-Application-SingleViewApp,点击Next:
输入项目名称,组织名称,bundleid,和使用的语言。由于不要需要使用单元测试和CoreDate,所以去掉底部的三个勾,如图配置好以后,点击Finish:
1.2 installpod
本项目使用CocoaPod管理第三方框架,所以需要将Pod引入项目。
使用命令行,切换到项目根目录,使用如下命令创建Pod:
此时在工程目录下Pod会创建一个文件,名为Podfile。需工程需要导入的第三方框架就添加在这个文件当中。使用vim编辑Podfile,加入DeviceManage-swift需要使用的第三方库,修改Podfile文件为:
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
use_frameworks!
target 'DeviceManage-swift' do
# Pods for DeviceManage-swift
pod 'AFNetworking' , '~> 3.1.0'
pod 'SVProgressHUD'
pod 'SDCycleScrollView', '~> 1.73'
pod 'SDAutoLayout'
pod 'MJRefresh'
pod 'JPush'
pod 'AMapLocation'
pod 'SDWebImage'
pod 'SnapKit'
pod 'HandyJSON', '~> 4.2.0'
pod 'SwiftyJSON'
end
依次说明一下这几个第三方库的作用:
- AFNetworking:第三方网络连接库,在本项目中并不会拿AFNetworking直接访问网络,而是将AFNetworking封装以后使用。目的是为了封装BaseURL、封装解析类型、网络请求日志等等,具体封装过程会在之后章节介绍。
- SVProgressHUD:loadiong时显示的小圆圈,在耗时的网络请求中会使用SVProgressHUD显示loading界面。
- SDCycleScrollView:循环轮播图。如果自己用UIScrollView来实现轮播图,会出现滚动到最后一张图片的时候无法滚动到第一张图,形成循环轮播。想要自己实现也是可以的,但是比较复杂,这里直接使用第三方框架。
- SDAutoLayout:自动布局框架。和Masonry类似,SDAutoLayout主要用来布局Cell。底层使用AutoLayout引擎。
- MJRefresh:TableView的下拉刷新和上拉加载组件。用在需要手动下拉刷新,获取需要分页的TableView。
- DOPDropDownMenu-Enhanced:使用在TableView上,用来显示筛选或排序类型的组件,点击可以显示下拉选项。
- JPush:极光推送。一个第三方推送SDK,用来接收推送消息。可以对设备设置别名,分组,从而实现分组或对个别用户进消息推送。
- AMapLocation:高德地图定位组件,用于获取设备当前位置,可以根据需求设置定位精度,对设备进行单次定位或是持续定位,获取高德坐标。
- SDWebImage:这个类库提供一个UIImageView类别以支持加载来自网络的远程图片。具有缓存管理、异步下载、同一个URL下载次数控制和优化等特征。
- SnapKit:一个经典的Swift版的第三方库,专门用于项目的自动布局。
- HandyJSON:采用Swift反射+内存赋值的方式来构造Model实例,保持原汁原味的Swift类定义。
- SwiftyJSON:SwiftyJSON是个使用Swift语言编写的开源库,可以让我们很方便地处理JSON数据(解析数据、生成数据)。
保存Podfile后,在Podfile当前目录下执行pod install命令,安装第三方库。
如图所示安装成功后,pod会把第三方库和工程合并到一个workspace中,所以现在需要从DeviceManage-swift.xcworkspace文件打开工程。打开后可以看到集成的第三方库:
需要使用第三方库的时候,只需要导入头文件,直接使用就可以了。项目直接把第三方库交给了CocoaPod管理了。
1.3 整理项目目录
一般iOS项目会使用MVC的设计模式进行开发,MVC的设计模式可以降低开发的耦合性、提高组件的重用性、提高可维护性,最重要的是可以使开发者条理清晰。Apple的UIKit等系统库都大量使用了MVC设计模式,所以本项目也将会在MVC的设计模式上进行开发。
首先需要整理项目目录,便于之后的开发和文件的分类。项目按照功能分类,在各个功能下分为三个模块:Model、Controller、View,在DeviceManager目录下创建好空文件夹,如下所示:
这里需要说明一下:
- 项目分为五个功能模块:首页、登录、购物车、咨询、我的。因为本项目使用MVC设计模式,所以每个功能模块下又分成M、V、C三个模块。
- 在Model文件夹中存放数据模型类,用来解析并转换JSON字符串为JSON对象;在View文件夹中存放视图类,用来显示UI;在Controller文件夹中存放控制器类,Controller是Model和View通信的桥梁,Controller通过请求获取数据并使用Model将JSON字符串转化为JSON对象传给View,用户对于View的操作,View会通知Controller,Controller处理以后改变Model。
- Framework(SDSY/Framework)文件夹中存放不支持CocoaPod的第三方库来手动管理。
- Tools(SDSY/Classes/Tools)文件夹中存放一些公共的工具类,比如:自定义网络框架、Category、全局定义、基础类(BaseClass)等等。
2. 封装AFNetworking
2.1 创建网络工具类
项目一般都会封装一层业务层的网络框架,这样可以统一请求网络请求接口,记录或打印网络日志,封装请求格式和解析格式等等。本项目底层网络框架采用AFNetworking,对AFNetworking进行了如下的业务封装:
- 单例方式获取网络工具类
- 封装AFNetworking两种请求方法(GET/POST)为一种,实现唯一的请求方法获取数据
- 封装请求的BaseURL
- 封装支持的解析类型(acceptableContentTypes)
- 封装可以手动关闭打开的打印网络请求日志,包括请求内容(请求类型、请求地址、请求内容)、请求获得的JSON、请求失败时的错误信息
- 封装返回的内容(服务器返回数据,请求错误等)
NetworkTool类就是本项目对AFNetworking的一层业务封装,具体代码如下:
NetworkTool.swift(SDSY/SDSY/Classes/Tools(工具)/NetworkTool.swift):
import Foundation
import AFNetworking
// 定义枚举类型
enum HTTPRequestType : Int{
case GET = 0
case POST
}
class NetworkTools: AFHTTPSessionManager {
// 设计单例 let是线程安全的
static let shareInstance : NetworkTools = {
let tools = NetworkTools()
tools.responseSerializer.acceptableContentTypes?.insert("text/html")
return tools
}()
}
// 封装请求方法
extension NetworkTools {
func request(methodType : HTTPRequestType, urlString : String, parameters : [String : AnyObject], finished :@escaping (_ result : AnyObject?, _ error : Error?)-> ()) {
// 1 成功回调
let successCallBack = {(task :URLSessionDataTask, result : Any) in
finished(result as AnyObject?, nil)
}
// 2 失败回调
let failureCallBack = {(task : URLSessionDataTask?, error :Error) in
finished(nil, error)
}
if methodType == .GET {
// get请求
get(urlString, parameters: parameters, progress: nil, success: successCallBack, failure: failureCallBack)
}else {
// post请求
post(urlString, parameters: parameters, progress: nil, success: successCallBack, failure: failureCallBack)
}
}
}
注意到上面的几个宏定义,需要加入到Const.swift文件中:
import UIKit
let BASE_URL = "http://192.168.0.108:8080/DeviceManage/"
对以上宏定义进行解释:
- BASE_URL:定义请求的基地址。
2.2创建Model解析类
网络框架已经将请求服务器返回的JSON字符串转换为了NSDictionary,如果我们之间使用NSDictionary来存取数据会十分的不方便。比如:每次读取或者写入时都需要使用Key-Value的方式进行,而Value的类型是id类型,非常的不直观。如果使用对象作为数据模型就会使开发更方便,出错率更低。所以项目需要一个将JSON字符串转化为JSON对象的类。
本项目的数据模型解析类的构造如下:BasaModel类是所有数据模型的父类,BasaModel负责解析JSON字符串为子类的属性。具体实现如下,BaseModel.h(SDSY/SDSY/Classes/Tools(工具)/BaseModel.swift):
import UIKit
import HandyJSON
class BaseModel: HandyJSON {
required init() {
}
}
1HandyJSON支持 JSON直接转Model,定义class时,有两点注意:
必须遵循HandyJSON协议
需要实现空的initializer (当然Struct结构体 可以不需要init())
3. 实现登录模块功能
3.1 创建用户信息模型UserInfoModel类
User登录使用的Model为UserInfoModel。该Model类封装了如下功能:
- 作为Model类最基本的用途,存储数据(学生ID,登录凭证,凭证过期时间等)
- 单例,在一个App的声明周期内存储用户登录信息
- 获取当前用户登录状态
- 退出登录
- 持久化储存用户登录信息,用于第二次打开App的自动登录
UserInfoModel作为一个全局单例,控制用户的登录状态与用户登录信息。
UserInfoModel.swift(SDSY/SDSY/Classes/Login(登录)/Model/UserInfoModel.swift):
import Foundation
import SwiftyJSON
enum LoginType:Int {
case AutoLogin = 1 // 自动登录
case GeneralLogin = 2 // 普通账号密码登录
case NoToken = 3 // 不存在token
case PastToken = 4 // token过期
}
class UserInfoModel:NSObject,NSCoding{
// 单例 - 避免重复从沙盒加载归档文件
static var shareInstance = UserInfoModel()
var UserID:Int?
var UserName:String?
var UserPassword:String?
//获取数据
override init() {
super.init()
let fileData = NSMutableData(contentsOfFile: self.savePath())
if fileData != nil {
let unarchiver = NSKeyedUnarchiver(fo