代码之家  ›  专栏  ›  技术社区  ›  user8397599

带有Json解析的Swift中的CollectionView无限滚动

  •  -1
  • user8397599  · 技术社区  · 8 年前

    我用json解析编写了collectionView无限滚动的代码。接下来,每次要查看20个数据。打印完20个数据后,我会显示页脚。

    这是我的全部代码:

    import Foundation
    
    import UIKit
    
    
    enum LoadMoreStatus{
    
        case loading
        case finished
        case haveMore
    }
    
    class Product: NSObject {
    
        var id: Int?
        var category_id: Int?
        var image: String?
        var name: String?
        var ar_name: String?
    
        var ar_description: String?
        var price: NSNumber?
        var quantity: String?
        var is_featured: String?
        var seller_id: String?
        var payment_required: String?
        var is_editors_choice: String?
        var created_at: String?
        var updated_at: String?
    
    }
    
    
    let categoryCellid = "categoryCellid"
    
    class ProductByCategoryCollectionView: UICollectionViewController, UICollectionViewDelegateFlowLayout {
    
    
    
        var headercellId = "headercellId"
    
        var footerCellid = "firstfootercellid"
        var numberOfCells = 5
        var loadingStatus = LoadMoreStatus.haveMore
    
    
        var arrProduct = [Product]()
        var category_id:Int = 0;
        var product_count:Int = 0;
    
        func reloadData(){
    
            collectionView?.reloadData()
            if numberOfCells > 0 {
                collectionView?.scrollToItem(at: IndexPath(row: 0, section: 0), at: .left, animated: true)
            }
        }
    
        func loadMore() {
    
            if numberOfCells >= arrProduct.count{ // here will show untill 22
                loadingStatus = .finished
                collectionView?.reloadData()
                return
            }
    
    
    
            Timer.schedule(delay: 2) { timer in
                self.numberOfCells += 10
                self.collectionView?.reloadData()
            }
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
    
    
           self.getPropductListByCategory()
    
    
    
            collectionView?.backgroundColor = .white
    
            navigationItem.title = "Product"
            navigationItem.backBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
            navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Sort By", style: .plain, target: nil, action: nil)
    
    
    
            self.setupHeaderView()
    
    
    
    
            collectionView?.register(ProductByCategoryCollectionViewCell.self, forCellWithReuseIdentifier: categoryCellid)
    
            collectionView?.register(ProductByCategoryFooterCell.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: footerCellid)
    
        }
    
    
        override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
            var text=""
            switch UIDevice.current.orientation{
            case .portrait:
                text="Portrait"
            case .portraitUpsideDown:
                text="PortraitUpsideDown"
            case .landscapeLeft:
                text="LandscapeLeft"
            case .landscapeRight:
                text="LandscapeRight"
            default:
                text="Another"
            }
            NSLog("You have moved: \(text)")
    
            collectionView?.reloadData()
    
        }
    
    
    
        func showCategoryDetailSegue() {
    
            let detailcontroller = UIViewController()
            navigationController?.pushViewController(detailcontroller, animated: true)
        }
    
    
    
    
        func sortBtnTarget() {
    
        }
    
    
        func filterBtnTarget() {
    
        }
    
        let dividedLine: UIView = {
            let view = UIView()
    
            view.backgroundColor = UIColor(white: 0.4, alpha: 0.4)
            return view
    
        }()
    
        let totalItemLabel: UILabel = {
            let label = UILabel()
    
            label.text = ""
            label.textAlignment = .center
            label.font = UIFont.systemFont(ofSize: 15)
            label.backgroundColor = UIColor.white
    
    
            return label
        }()
    
    
    
        let dividerLineView: UIView = {
            let view = UIView()
            view.backgroundColor = UIColor.white
    
            return view
        }()
    
    
    
        func setupHeaderView(){
    
    
            view.backgroundColor = UIColor(white: 0.4, alpha: 0.4)
    
    
    
            dividedLine.frame = CGRect(x: 0, y: 95, width: view.frame.width, height: 1)
            totalItemLabel.frame = CGRect(x: 0, y: 55, width: view.frame.width, height: 40)
    
    
    
            view.addSubview(totalItemLabel)
    
            view.addSubview(dividedLine)
    
    
        }
    
    
    
        override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    
    
         return arrProduct.count
    
        }
    
        override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    
            if(indexPath.row==arrProduct.count-1){
                if loadingStatus == .haveMore {
                    self.perform(#selector(ProductByCategoryCollectionView.loadMore), with: nil, afterDelay: 0)
                }
            }
    
    
    
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: categoryCellid, for: indexPath) as! ProductByCategoryCollectionViewCell
            cell.callProductObject4Cell = arrProduct[indexPath.item]
    
    
    
            return cell
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            return CGSize(width: 172, height: 300)
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
            return UIEdgeInsetsMake(32, 10, 0, 10)
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
            return 0
        }
    
        override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    
    
            let layout = UICollectionViewFlowLayout()
          layout.scrollDirection = .horizontal
            let controller1 = UICollectionViewController(collectionViewLayout: layout)
            navigationController?.pushViewController(controller1, animated: true)
    
        }
        override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
            super.viewWillTransition(to: size, with: coordinator)
    
            collectionView?.collectionViewLayout.invalidateLayout()
        }
    
    
        override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
            var footerView:ProductByCategoryFooterCell!
    
    
            if (kind ==  UICollectionElementKindSectionFooter) && (loadingStatus != .finished){
                footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerCellid, for: indexPath) as! ProductByCategoryFooterCell
    
            }
    
            return footerView
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
    
            return (loadingStatus == .finished) ? CGSize.zero : CGSize(width: self.view.frame.width, height: 50)
    
        }
    
    
    }
    
    
    
    
    class ProductByCategoryCollectionViewCell: UICollectionViewCell {
    
        var callProductObject4Cell: Product?{
            didSet {
                productLabel.text = callProductObject4Cell?.name
    
    
    
                if let price = callProductObject4Cell?.price {
                    //priceLabel.text = "$\(price)"
                    priceLabel.text = "\(price) TK"
                } else {
                    priceLabel.text = ""
                }
    
    
    
    
                if let profileImageUrl = callProductObject4Cell?.image {
                    productImage.loadImageUsingUrlString(profileImageUrl)
                }
    
    
            }
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            setupcategoryCell()
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        let productImage: UIImageView = {
            let image = UIImageView()
    
            image.image = UIImage(named: "default")
            image.contentMode = .scaleAspectFit
            image.layer.borderWidth = 1
            image.layer.borderColor = UIColor.orange.cgColor
            image.layer.masksToBounds = true
            return image
        }()
    
        let productLabel: UILabel = {
            let label = UILabel()
            label.text = "productName"
            label.textColor = .black
            label.numberOfLines = 0
            label.font = UIFont.boldSystemFont(ofSize: 10)
    
            return label
        }()
    
        let priceLabel: UILabel = {
            let label = UILabel()
            //        label.backgroundColor = .lightGray
            label.text = ""
            label.textColor = .orange
            label.font = UIFont.systemFont(ofSize: 13)
    
            return label
        }()
    
        func setupcategoryCell() {
    
            addSubview(productImage)
            addSubview(productLabel)
            addSubview(priceLabel)
    
            addConstraintsWithFormat("H:|[v0]|", views: productImage)
            addConstraintsWithFormat("V:|[v0(230)]-2-[v1][v2(10)]-5-|", views: productImage,productLabel, priceLabel)
    
            addConstraintsWithFormat("H:|[v0]|", views: productLabel)
    
            addConstraintsWithFormat("H:|[v0]|", views: priceLabel)
        }
    }
    
    
    
    class ProductByCategoryFooterCell: UICollectionViewCell {
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            backgroundColor = .white
            setupCell()
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        let menuHeaderLabel: UILabel = {
            let label = UILabel()
            label.text = "loadin more waiting"
            label.textColor = .green
            label.textAlignment = .center
            label.font = UIFont.boldSystemFont(ofSize: 15)
            label.translatesAutoresizingMaskIntoConstraints = false
            return label
        }()
    
        func setupCell() {
    
            addSubview(menuHeaderLabel)
    
    
    
            addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
    
            addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-5-[v0(30)]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
    
        }
    }
    
    
    
    extension Timer {
    
        class func schedule(delay: TimeInterval, handler: @escaping (Timer!) -> Void) -> Timer {
            let fireDate = delay + CFAbsoluteTimeGetCurrent()
            let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, 0, 0, 0, handler)
            CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
            return timer!
        }
    
        class func schedule(repeatInterval interval: TimeInterval, handler: @escaping (Timer!) -> Void) -> Timer {
            let fireDate = interval + CFAbsoluteTimeGetCurrent()
            let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, interval, 0, 0, handler)
            CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
            return timer!
        }
    }
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   Nathan Tuggy TonyLuigiC    8 年前
    enum LoadMoreStatus {
        case loading
        case finished
        case haveMore
    }
    
    class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
    
        var verticalDataSource = [String]()
    
        var firstCellid = "firstcellid"
        var firstFooterCellid = "firstfootercellid"
        var numberOfCells = 5
        var loadingStatus = LoadMoreStatus.haveMore
    
        func reloadData() {
            //numberOfCells = 10
            collectionView?.reloadData()
            if numberOfCells > 0 {
                collectionView?.scrollToItem(at: IndexPath(row: 0, section: 0), at: .left, animated: true)
            }
        }
    
        func loadMore() {
            if numberOfCells >= 40 { 
                // here will show untill finished number
                loadingStatus = .finished
                collectionView?.reloadData()
                return
            }
    
            // Replace code with web service and append to data source
            Timer.schedule(delay: 2) { timer in
                self.numberOfCells += 2
                self.collectionView?.reloadData()
            }
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.automaticallyAdjustsScrollViewInsets = false
    
            collectionView?.register(VerticalCollectionViewCell.self, forCellWithReuseIdentifier: firstCellid)
            collectionView?.register(VerticalCollectionViewCell2.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: firstFooterCellid)
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        //MARK - Rotation methods
    
        override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
            var text=""
    
            switch UIDevice.current.orientation {
            case .portrait:
                text="Portrait"
            case .portraitUpsideDown:
                text="PortraitUpsideDown"
            case .landscapeLeft:
                text="LandscapeLeft"
            case .landscapeRight:
                text="LandscapeRight"
            default:
                text="Another"
            }
    
            NSLog("You have moved: \(text)")
    
            collectionView?.reloadData()
        }
    
        override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return numberOfCells
        }
    
        // The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
        override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
            if(indexPath.row==numberOfCells-1) {
                if loadingStatus == .haveMore {
                    self.perform(#selector(ViewController.loadMore), with: nil, afterDelay: 0)
                }
            }       
    
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: firstCellid, for: indexPath) as! VerticalCollectionViewCell
            cell.menuHeaderLabel.text = "Labet text no \(indexPath.item)"
            return cell
    
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            return CGSize(width: self.view.frame.width, height: 100)
        }
    
        override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
            var footerView:VerticalCollectionViewCell2!
    
            if (kind ==  UICollectionElementKindSectionFooter) && (loadingStatus != .finished) {
                footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: firstFooterCellid, for: indexPath) as! VerticalCollectionViewCell2
            }
    
            return footerView
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
            return (loadingStatus == .finished) ? CGSize.zero : CGSize(width: self.view.frame.width, height: 50)
        }        
    }
    
    class VerticalCollectionViewCell: UICollectionViewCell {
    
        override init(frame: CGRect) {
            super.init(frame: frame)
    
            setupCell()
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        let menuHeaderLabel: UILabel = {
            let label = UILabel()
            label.text = "lable text"
            label.textColor = .orange
            label.textAlignment = .center
            label.font = UIFont.boldSystemFont(ofSize: 15)
            label.translatesAutoresizingMaskIntoConstraints = false
    
            return label
        }()
    
        func setupCell() {
            addSubview(menuHeaderLabel)
    
            // addTaskButton.addTarget(self, action: #selector(MenuHeader.addTask), for: .touchUpInside)
    
            addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
    
            addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-5-[v0(30)]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
        }
    }