swift笔记(五)
2017-07-14 本文已影响20人
阿凡提说AI
1.下拉刷新
refreshControl = UIRefreshControl()
let otherView = UIView()
otherView.frame = CGRect(x: 0, y: 0, width: 400, height: 44)
otherView.backgroundColor = UIColor.purpleColor()
refreshControl?.addSubview(otherView)
/*
1.UIRefreshControl只要拉到一定程度无论是否松手会都触发下拉事件
2.触发下拉时间之后, 菊花不会自动隐藏
3.想让菊花消失必须手动调用endRefreshing()
4.只要调用beginRefreshing, 那么菊花就会自动显示
5.如果是通过beginRefreshing显示菊花, 不会触发下拉事件
*/
refreshControl?.addTarget(self, action: Selector("loadMoreData"), forControlEvents: UIControlEvents.ValueChanged)
RefreshView.swift
import UIKit
import SnapKit
class XMGRefreshControl: UIRefreshControl {
override init() {
super.init()
// 1.添加子控件
addSubview(refreshView)
// 2.布局子控件
refreshView.snp_makeConstraints { (make) -> Void in
make.size.equalTo(CGSize(width: 150, height: 50))
make.center.equalTo(self)
}
// 3.监听UIRefreshControl frame改变
addObserver(self, forKeyPath: "frame", options: NSKeyValueObservingOptions.New, context: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit
{
removeObserver(self, forKeyPath: "frame")
}
override func endRefreshing() {
super.endRefreshing()
refreshView.stopLoadingView()
}
/// 记录是否需要旋转
var rotationFlag = false
// MARK: - 内部控制方法
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if frame.origin.y == 0 || frame.origin.y == -64
{
// 过滤掉垃圾数据
return
}
// 判断是否触发下拉刷新事件
if refreshing
{
// 隐藏提示视图, 显示加载视图, 并且让菊花转动
refreshView.startLoadingView()
return
}
// 通过观察发现: 往下拉Y越小, 往上推Y越大
if frame.origin.y < -50 && !rotationFlag
{
rotationFlag = true
NJLog("往上旋转")
refreshView.rotationArrow(rotationFlag)
}else if frame.origin.y > -50 && rotationFlag
{
rotationFlag = false
NJLog("往下旋转")
refreshView.rotationArrow(rotationFlag)
}
}
// MARK: -懒加载
private lazy var refreshView: RefreshView = RefreshView.refreshView()
}
class RefreshView: UIView {
/// 菊花
@IBOutlet weak var loadingImageView: UIImageView!
/// 提示视图
@IBOutlet weak var tipView: UIView!
/// 箭头
@IBOutlet weak var arrowImageView: UIImageView!
class func refreshView() -> RefreshView {
return NSBundle.mainBundle().loadNibNamed("RefreshView", owner: nil, options: nil).last as! RefreshView
}
// MARK: - 外部控制方法
/// 旋转箭头
func rotationArrow(flag: Bool)
{
var angle: CGFloat = flag ? -0.01 : 0.01
angle += CGFloat(M_PI)
/*
transform旋转动画默认是按照顺时针旋转的
但是旋转时还有一个原则, 就近原则
*/
UIView.animateWithDuration(2.0) { () -> Void in
self.arrowImageView.transform = CGAffineTransformRotate(self.arrowImageView.transform, angle)
}
}
/// 显示加载视图
func startLoadingView()
{
// 0.隐藏提示视图
tipView.hidden = true
if let _ = loadingImageView.layer.animationForKey("lnj")
{
// 如果已经添加过动画, 就直接返回
return
}
// 1.创建动画
let anim = CABasicAnimation(keyPath: "transform.rotation")
// 2.设置动画属性
anim.toValue = 2 * M_PI
anim.duration = 5.0
anim.repeatCount = MAXFLOAT
// 3.将动画添加到图层上
loadingImageView.layer.addAnimation(anim, forKey: "lnj")
}
/// 隐藏加载视图
func stopLoadingView()
{
// 0.显示提示视图
tipView.hidden = false
// 1.移除动画
loadingImageView.layer.removeAllAnimations()
}
}
2.显示提醒消息
/// 显示刷新提醒
private func showRefreshStatus(count: Int)
{
// 1.设置提醒文本
tipLabel.text = (count == 0) ? "没有更多数据" : "刷新到\(count)条数据"
tipLabel.hidden = false
// 2.执行动画
UIView.animateWithDuration(1.0, animations: { () -> Void in
// UIView.setAnimationRepeatAutoreverses(true)
self.tipLabel.transform = CGAffineTransformMakeTranslation(0, 44)
}) { (_) -> Void in
UIView.animateWithDuration(1.0, delay: 2.0, options: UIViewAnimationOptions(rawValue: 0), animations: { () -> Void in
self.tipLabel.transform = CGAffineTransformIdentity
}, completion: { (_) -> Void in
self.tipLabel.hidden = true
})
}
}
3.缓存行高
/// 缓存行高
private var rowHeightCaches = [String: CGFloat]()
// 返回行高
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let viewModel = statuses![indexPath.row]
let identifier = (viewModel.status.retweeted_status != nil) ? "forwardCell" : "homeCell"
// 1.从缓存中获取行高
guard let height = rowHeightCaches[viewModel.status.idstr ?? "-1"] else
{
NJLog("计算行高")
// 缓存中没有行高
// 2.计算行高
// 2.1获取当前行对应的cell
let cell = tableView.dequeueReusableCellWithIdentifier(identifier) as! HomeTableViewCell
// 2.1缓存行高
let temp = cell.calculateRowHeight(viewModel)
rowHeightCaches[viewModel.status.idstr ?? "-1"] = temp
// 3.返回行高
return temp
}
// 缓存中有就直接返回缓存中的高度
return height
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// 释放缓存数据
rowHeightCaches.removeAll()
}