项目需求:做一个图片浏览器,点击图片查看大图,大图模式下,左右滚动能查看不同的图片.
项目的主要核心技术:图片的弹出和消失动画
项目源代码: Photo-Browser
一.对代码进行重构
1.对代码进行抽取划分
1.1 为什么要对代码进行抽取?
swift中,代码全部写在一起,阅读性极差
2.如何对代码进行抽取?
2.1在oc中,可以把功能模块抽取一个个方法
2.2swift中,专门提供 extension ,可以对原有的类进行扩展
3.怎么使用extension 抽取代码?
3.1 把一些方法写在extension(扩展)里面,这样能减少viewDidLoad里面的代码
3.2 extension可以写多个,这样就可以把不同的功能模块 ,写在不同的扩展里面
二.项目基本设置
1.修改bundleID
2.部署版本
3.设置项目图片,启动图片
4.对文件夹目录进行划分
三.首页布局
1.让首页为UICollectionViewController
2.设置数据源
3.自定义布局
3.1 创建一个源文件,继承自UICollectionViewFlowLayout
3.2 重写 prepareLayout
3.3 设置布局的相关属性
4.如何设置StoryBoard中的UICollectionViewController的布局
4.1 在StoryBoard中选中collectionView
4.2 在属性里找到 layout 设置为自定义 custom
4.3 在下面的class里面 把自定义布局的类名写进去即可
四.网络工具类的封装
1.集成CocoaPods, 并导入AFNetworking框架
1.1 打开终端,进入项目路径下 cd 路径
1.2 创建PodFile文件 pod init
1.3 配置PodFile文件 ,写入要导入的框架
1.4 导入框架 pod install —no-repo-update / 或 pod intall
1.41 pod install 会更新本地库(本地已有的框架也会更新) 速度相对较慢
1.42 pod install —no-repo-update 不会更新本地库,速度相对来说快点
2.封装工具类
2.1 将工具类设计成单例对象
防止别人修改
防止多线程访问,创建多个对象
2.2 swift中单例的设置方式
static let shareInstance : NetworkTools = NetworkTools()
2.3 可以让工具类,直接继承自用到框架的一个类
好处:自己就是这个类的子类,拥有这个类的所有方法和属性,用的时候直接自己就能调用
3.封装网络请求方法
func requestData (type : Int , urlString : String ,
parameters : [ String : NSObject] , callBack :
(result : AnyObject? , error : NSErroe?) -> () )
func reqeustData(type : RequestType, urlString : String,
parameters : [String : NSObject], finishedCallback :
(result : AnyObject?, error : NSError?) -> ()) { }
4.把方法里面的闭包抽取出来
4.1 为什么要抽取?
方法里面闭包很长,代码很乱,造成阅读性差
4.2 怎么抽取?
定义一个成员属性 为闭包类型 把方法里面的闭包,用属性名 替换
五.项目集成工具类
把封装好的工具类,直接拖到项目文件中
六.请求网络数据
1.在控制器中调用工具类封装好的网络请求方法
2.解析数据
要对获取到的数据进行类型转换,应为从网络加载的数据类型为AnyObject
guard let resultDict = result as? [String : NSObject] else {
return
}
guard let dataArray = resultDict["data"] as? [[String : NSObject]] else {
return
}
3.字典转模型
3.1 创建模型
3.2 通过kvc手动转模型 , 要重写 override func setValue(value: AnyObject?, forUndefinedKey key: String) {}
3.3 注意: 在闭包中 self. 也不可以省略
七.自定义cell,展示数据
1.创建cell继承自UICollectionViewCell
2.在cell里面定义模型属性
3.监听属性改变(相当于oc的重写set方法)
在属性监听器(willSet, didSet) 这里用didSet方法里面给模型里面的属性赋值
八.加载更多数据
1.什么时候加载更多的数据?
当最后一个cell出现的时候
2.怎么监听最后一个cell是否出现在屏幕上
通过cell(item)的下标值(从0开始)是否等于数组长度 - 1
// 最后一个cell已经出现
if indexPath.item == shops.count - 1 {
indexPath.item 相当于 tableView 的 indexPath.row
loadHomeData(shops.count)
}
3.怎么加载更多数据
和加载数据一样,只不过多传一个参数offset
九.弹出图片浏览器
1.创建图片浏览器的控制器对象UIViewController
2.弹出控制器
2.1 监听cell的点击
2.2 创建图片浏览器控制器对象
2.3 设置图片浏览器控制器对象的弹出样式
photoBrowserVc.modalTransitionStyle = .FlipHorizontal
2.4 把控制器modal出来
十.布局图片浏览器
1.布局UICollectionView
1.1 创建UICollectionView
1.2 把UICollectionView添加到控制器的View上
1.3 设置数据源
1.4 自定义布局
2.布局两个按钮
2.1 创建两个按钮
2.2 设置按钮的frame
2.3 对UIButton进行extension(扩展)
2.31 为什么要进行扩展
创建出来的按钮,要设置图片,字体,和文字,一个个设置太麻烦,想让按钮创建出来就有这些属性
2.32 怎么进行扩展?
对UIButton进行extension(扩展) 扩充一个类型方法,在类方法里面封装好这些属性
class func createBtn(title : String, bgColor : UIColor,
fontSize : CGFloat) -> UIButton {
let btn = UIButton()
btn.backgroundColor = bgColor
btn.setTitle(title, forState: .Normal)
btn.titleLabel?.font = UIFont.systemFontOfSize(fontSize)
return btn
}
2.4 这样创建还不是很方便,我们可以给UIbutton扩展构造函数,创建的时候直接设置这些属性
2.41 注意:在extension中扩充构造函数,只能扩充便利构造函数
2.42 什么是便利构造函数?
1.必须在init前面加上convenience
2.必须在init方法中 调用self.init()
convenience init(title : String, bgColor : UIColor, fontSize : CGFloat) {
self.init()
setTitle(title, forState: .Normal)
backgroundColor = bgColor
titleLabel?.font = UIFont.systemFontOfSize(fontSize)
}
3.监听按钮的点击
3.1 xcode7.2 和xcode7.3中监听方法的写法不太一样
Xcode7.2 --> 1> Selector("方法的名称") 2> ""
Xcode7.3 --> #selector(类.方法名称)
3.2 如果点击按钮调用的方法前面加上private 调用会报错
3.21 为什么会报错
找不到方法
3.22 监听事件实质就是发送一条消息
3.23 发送消息的过程是:
1.将消息包装成@SEL 2.通过@SEL去类中的方法列表中找对相应的方法(函数)
3.34 在swift中,如果一个函数前面加上private,那么该函数就不会被添加到消息(映射)列表中
3.35 如果在private前面加上@objc ,就会保留oc的特性, 该方法依然会添加到消息列表中
3.3 解决问题的方法就是 在private前面加上@objc 或者不写private
想了解更多请查看:轻松学习swift--swift项目初体验(二)
项目源代码: Photo-Browser
喜欢就给个星星吧