2016年1月

团购页面模拟,swift版本

继续熟悉UITableView和之前的内容
这个只是模拟一下页面,页面整个就是一个UITableView,UITableView有一个自定义的头和尾,然后就是自定义的cell
需要注意的点:自定义xib,和xib的使用,自定义UITableViewCell,自定义代理协议,dispatch_after的使用

加载数据,注意kvc的读取的数据的键值要与对象的属性名称一致
//
//  Goods.swift
//  GroupBuying
//
//  Created by admin on 16/1/5.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class Goods: NSObject {
    var buyCount:NSString!
    var icon:NSString!
    var price:NSString!
    var title:NSString!
    //根据文件初始化对象数组
    class func instanceWithFile()->[Goods]
    {
        //读取plist文件内容
        let data = NSArray(contentsOfFile: NSBundle.mainBundle().pathForResource("tgs", ofType: "plist")!)
        //循环初始化对象数组
        var goods:[Goods] = []
        for var i = 0;i < data?.count;i++
        {
            goods.append(self.instanceWithDic(data![i] as! [String : AnyObject]))
        }
        return goods
    }
    //根据字典初始化数组
    class func instanceWithDic(dic:[String : AnyObject])->Goods
    {
        let goods = Goods()
        //使用kvc赋值
        goods.setValuesForKeysWithDictionary(dic)
        return goods
    }
}
使用xib自定义cell,需要注意的是,要在xib的属性里面设置好 Identifier ,不然从缓冲池中取不到内容,依然会重复的创建与销毁对象
//
//  GoodsTableCell.swift
//  GroupBuying
//
//  Created by admin on 16/1/5.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit
//自定义 UITableViewCell 类
class GoodsTableCell: UITableViewCell {


    @IBOutlet weak var title: UILabel!
    @IBOutlet weak var price: UILabel!
    @IBOutlet weak var buyCount: UILabel!
    @IBOutlet weak var icon: UIImageView!

    class func instanceWithTableView(tableView:UITableView,goods:Goods)->GoodsTableCell
    {
        //这个值要和在xib属性栏设置的 Identifier 一致
        let id = "goodsTableCell"
        //从缓存池中去内容,避免不必要的创建和销毁对象
        var temp:UITableViewCell! = tableView.dequeueReusableCellWithIdentifier(id)
        //因为可能缓存池是空的,取不出内容,所以这里做下处理
        if temp == nil
        {
            temp = NSBundle.mainBundle().loadNibNamed("GoodsTableCell", owner: nil, options: nil).last as! GoodsTableCell
        }
        //从缓存池取出的是 UITableViewCell 这里需要转换下,方便调用赋值方法
        let cell = temp as! GoodsTableCell
        //给子控件赋值
        cell.setData(goods)
        return cell
    }
    //设置子控件内容
    func setData(goods:Goods)
    {
        self.title.text = goods.title as String
        self.price.text = "¥\(goods.price as String)"
        self.buyCount.text = goods.buyCount as String + "人购买"
        self.icon.image = UIImage(imageLiteral: goods.icon as String)
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}
使用xib自定义footer,需要注意的是,dispatch_after的使用,和自定义协议
//
//  GoodsTableFooter.swift
//  GroupBuying
//
//  Created by admin on 16/1/5.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit
//定义代理协议
@objc protocol GoodsTableFooterLoadMoreDataButton:NSObjectProtocol
{
    optional func loadmoreDataButton()
}
class GoodsTableFooter: UIView {

    @IBOutlet weak var loadMoreButton: UIButton!
    @IBOutlet weak var loadMoreView: UIView!
    weak var delegate:GoodsTableFooterLoadMoreDataButton!
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
        // Drawing code
    }
    */
    //当从nib文件中初始化称对象时会执行这个方法
    override func awakeFromNib() {
        super.awakeFromNib()
        //设置按钮圆角效果
        self.loadMoreButton.layer.cornerRadius = 5
        //设置按钮点击事件
        loadMoreButton.addTarget(self, action: "loadData:", forControlEvents: UIControlEvents.TouchDown)
    }
    //快速实例化对象
    class func instance()->GoodsTableFooter
    {
        let footer = NSBundle.mainBundle().loadNibNamed("GoodsTableFooter", owner: nil, options: nil).last as! GoodsTableFooter
        return footer
    }
    //
    func loadData(sender:UIButton)
    {
        //隐藏button按钮,显示菊花
        sender.hidden = true
        //这里设置下延时执行,之前没用过的一种方式,这个参数有一些特别,而且没有提示。。。。记录下
        let minseconds = 2 * Double(NSEC_PER_SEC)
        let dtime = dispatch_time(DISPATCH_TIME_NOW, Int64(minseconds))
        dispatch_after(dtime, dispatch_get_main_queue(), { () -> Void in
            let check = self.delegate?.respondsToSelector("loadmoreDataButton")
            //因为代理和代理和方法都是可选类型,所以这里需要做下判断是否执行代理方法
            if check != nil && (check!) == true
            {
                self.delegate.loadmoreDataButton!()
            }
            self.loadMoreButton.hidden = false

        })
    }
}
使用xib自定义header,需要注意的是,因为这个头里面包含一个图片轮播,所以需要用到定时器,scallView代理方法
//
//  GoodsTableHeader.swift
//  GroupBuying
//
//  Created by admin on 16/1/6.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class GoodsTableHeader: UIView,UIScrollViewDelegate {

    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
        // Drawing code
    }
    */
    @IBOutlet weak var scallView: UIScrollView!
    @IBOutlet weak var pageControl: UIPageControl!
    //存放定时器,方便之后的停止
    var timer:NSTimer!
    //快速实例化的方法
    class func instance()->GoodsTableHeader
    {
        let header = NSBundle.mainBundle().loadNibNamed("GoodsTableHeader", owner: nil, options: nil).last as! GoodsTableHeader
        return header
    }
    //这个方法在xib从文件初始化成对象的时候调用
    override func awakeFromNib() {
        self.pageControl.numberOfPages = 5
        let w = self.scallView.frame.size.width
        let h = self.scallView.frame.size.height
        let y = self.scallView.frame.origin.y
        for var i = 0;i <= self.pageControl.numberOfPages;i++
        {
            let imageView:UIImageView = UIImageView()
            if i == self.pageControl.numberOfPages
            {
                imageView.image = UIImage(imageLiteral: "ad_" + String(format: "%02i", 0))
            }
            else
            {
                imageView.image = UIImage(imageLiteral: "ad_" + String(format: "%02i", i))
            }
            let x = CGFloat(i) * w
            imageView.frame = CGRectMake(x, y, w, h)
            self.scallView.addSubview(imageView)
        }
        self.scallView.contentSize = CGSizeMake(CGFloat(self.pageControl.numberOfPages) * w, h)
        self.scallView.pagingEnabled = true
        self.scallView.showsHorizontalScrollIndicator = false
        self.scallView.delegate = self
        self.startTimer()
    }
    //滚动过程设置 currentPage
    func scrollViewDidScroll(scrollView: UIScrollView) {
        var currentPage = Int((scallView.contentOffset.x + (0.5 * scallView.frame.size.width)) / scallView.frame.size.width)
        if currentPage > self.pageControl.numberOfPages - 1
        {
            currentPage = 0
        }
        self.pageControl.currentPage = currentPage
    }
    //手动拖动时,停止定时器
    func scrollViewWillBeginDragging(scrollView: UIScrollView) {
        self.timer.invalidate()
    }
    //手动拖动完毕时,继续定时器
    func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        self.startTimer()
    }
    func startTimer()
    {
        //定时器
        self.timer = NSTimer(timeInterval: 2, target: self, selector: "changeImage", userInfo: nil, repeats: true)
        let runLoop = NSRunLoop.currentRunLoop()
        runLoop.addTimer(self.timer, forMode: NSRunLoopCommonModes)
    }
    //切换到下一张图片
    func changeImage()
    {
        var offect = CGPointMake(0, 0)

        if self.pageControl.currentPage == 0 && self.scallView.contentOffset.x > 0
        {
            self.scallView.contentOffset = offect
        }

        offect = CGPointMake(self.scallView.frame.size.width * CGFloat(self.pageControl.currentPage + 1), self.scallView.contentOffset.y)
        UIView.animateWithDuration(1, animations: { () -> Void in
            self.scallView.contentOffset = offect
            })
    }
}
在控制器中调用,注意:完成了代理协议之后,要记得设置代理,刷新cell的方式

// // ViewController.swift // GroupBuying // // Created by admin on 16/1/5. // Copyright © 2016年 jin. All rights reserved. // import UIKit class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate,GoodsTableFooterLoadMoreDataButton { @IBOutlet weak var tableView: UITableView! lazy var goods:[Goods] = Goods.instanceWithFile() override func viewDidLoad() { super.viewDidLoad() self.tableView.dataSource = self self.tableView.delegate = self //设置cell高度 self.tableView.rowHeight = 150 //设置tableFooter,注意,这里的Footer和代理方法中返回Footer的那个方法设置的Footer可不一样 let footer = GoodsTableFooter.instance() footer.delegate = self self.tableView.tableFooterView = footer //设置header self.tableView.tableHeaderView = GoodsTableHeader.instance() // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.goods.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = GoodsTableCell.instanceWithTableView(self.tableView, goods: self.goods[indexPath.row]) return cell } // func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { // var footer:GoodsTableFooter = NSBundle.mainBundle().loadNibNamed("GoodsTableFooter", owner: nil, options: nil).last as! GoodsTableFooter // return footer // } // func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { // return 80 // } //代理Footer的加载更多数据的方法 func loadmoreDataButton() { let goods = Goods() goods.title = "鱼香肉丝" goods.price = "10" goods.buyCount = "30" goods.icon = "37e4761e6ecf56a2d78685df7157f097.png" //添加数据到cell数据的来源数组 self.goods.append(goods) //刷新cell,但是这个方法是刷新所有的cell,其实这里只添加了1个数据而已,虽然能达到效果,但是这个不好 // self.tableView.reloadData() //这个是重新刷新指定的cell,也就是说需要这个行之前就存在,这里加的行在之前是不存在的,所以会报错 // self.tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: self.goods.count - 1, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Fade) //这个方法是插入一行,这里用这个最好 self.tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: self.goods.count - 1, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Fade) } }

图片轮播swift版本

有几个需要注意的地方,scallView的常用属性,代理的使用,定时器的使用,定时器不同模式的区别,UIPageControl的使用

//
//  ViewController.swift
//  图片轮播
//
//  Created by admin on 15/12/31.
//  Copyright © 2015年 jin. All rights reserved.
//

import UIKit
//遵循了UIScrollViewDelegate协议,作为scallView的代理
class ViewController: UIViewController,UIScrollViewDelegate{

    @IBOutlet weak var scallView: UIScrollView!
    @IBOutlet weak var pageControl: UIPageControl!
    var timer:NSTimer!
    override func viewDidLoad() {
        super.viewDidLoad()

        let w = scallView.frame.size.width
        let h = scallView.frame.size.height
        let colnum = 5
        for var i = 1;i <= colnum + 1;i++
        {
            var imageView:UIImageView = UIImageView()
            //多添加一个图片,让轮播效果更顺眼
            if i > colnum
            {
                imageView.image = UIImage(imageLiteral: "img_01")
            }
            else
            {
                imageView.image = UIImage(imageLiteral: "img_" + String(format: "%02i", i))
            }
            let x = CGFloat(i - 1) * w
            imageView.frame = CGRectMake(x, 0, w, h)
            scallView.addSubview(imageView)
        }

        //scallView可拖动区域的大小
        scallView.contentSize = CGSizeMake(CGFloat(colnum) * w, 0)
        scallView.showsHorizontalScrollIndicator = false//去掉横向滚动条
        scallView.pagingEnabled = true//打开分页
        //设置UIPageControl的点的个数
        pageControl.numberOfPages = column
        //设置scallView的代理
        scallView.delegate = self
        //设置活动分页的颜色
        pageControl.currentPageIndicatorTintColor = UIColor.redColor()
        //设置活动分页之外分页的颜色
        pageControl.pageIndicatorTintColor = UIColor.blackColor()
        //添加定时器,自动切换图片
        self.addTimer()

    }
    //图片切换
    func imageChange()
    {
        var coordinates:CGPoint = CGPoint(x: 0,y: 0)
        //为了从最后一张切换到第一张的时候不那么突兀,这里需要处理
        if pageControl.currentPage == 0 && scallView.contentOffset.x > 0
        {
            coordinates = CGPoint(x: 0, y: scallView.contentOffset.y)
            self.scallView.contentOffset = coordinates
        }
        coordinates = CGPoint(x: CGFloat(pageControl.currentPage + 1) * scallView.frame.size.width, y: scallView.contentOffset.y)
        //动画效果
        UIView.animateWithDuration(1, animations: {
            self.scallView.contentOffset = coordinates
        })
    }
    //添加定时器的方法
    func addTimer()
    {
        //初始化定时器
        self.timer = NSTimer(timeInterval: 3, target: self, selector: "imageChange", userInfo: nil, repeats: true)
        //获得当前消息循环
        var runLoop = NSRunLoop.currentRunLoop()
        //把定时器以默认模式添加进当前消息循环,分为两种模式
//        runLoop.addTimer(self.timer, forMode: NSDefaultRunLoopMode)
        runLoop.addTimer(self.timer, forMode: NSRunLoopCommonModes)

    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    //scrollView代理方法,滚动时
    func scrollViewDidScroll(scrollView: UIScrollView) {
        //获得当前页数
        let currentPage = Int((scallView.contentOffset.x + (scallView.frame.size.width * 0.5)) / scallView.frame.size.width)
        //因为多加了一个图片,所以这里需要处理下
        if currentPage >= pageControl.numberOfPages
        {
            pageControl.currentPage = 0
        }
        else
        {
            pageControl.currentPage = currentPage
        }
    }
    //scallView代理方法,开始拖拽
    func scrollViewWillBeginDragging(scrollView: UIScrollView) {
        self.timer.invalidate()
    }
    //scallView代理方法,结束拖拽
    func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        //创建定时器并加入当前消息循环,默认模式
//        self.timer = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: "imageChange", userInfo: nil, repeats: true)
        self.addTimer()
    }

}