搜索VC实例(本地历史记录)

效果图


搜索界面

XLSearchViewController.swift

import UIKit
import YYCache
enum XLSearchType:Int {
    ///健康百科
    case healthyWiki = 1
    
}
class XLSearchViewController: BaseViewController {

    var cellWidth = SCREEN_WIDTH/2
    var historyArr : Array = []
    
    //默认搜索健康百科
    var placehoder = ""
    var searchType:XLSearchType = .healthyWiki
    var cacheName = NSCacheModuleKeys.searchHistory_wiki_info.rawValue
    
    override func viewDidLoad() {
        super.viewDidLoad()
        getSearchHistory()
        createUI()
        viewBlocks()
    }

    override func viewWillAppear(_ animated: Bool) {
        self.navigationController?.setNavigationBarHidden(true, animated: false)
    }
    lazy var searchHeaderView:XLSearchHeaderView = {
        let view = XLSearchHeaderView.init(placehoder: placehoder)
        return view
    }()
    lazy var historyLabel: UILabel = {
        let label = UILabel.labelWithTitle(text: "搜索历史",
                                           textColor: CNaviItemDisableColor,
                                           textFont: 12,
                                           textAlignment: .left, specialFont: nil)
        return label
    }()
    lazy var clearBut: UIButton = {
        let but = UIButton.buttonWithImage(title: nil, normalImage: R.image.search_clear_history()!, highlightImage: nil, selectedImage: nil)
        but.addTarget(self, action: #selector(clearAction), for: .touchUpInside)
        return but
    }()

    lazy var historyCollectionView: UICollectionView = {
        
        let collectV = UICollectionView.init(frame: CGRect.zero, collectionViewLayout: historyCollectionViewFlowLayout)
        collectV.delegate = self
        collectV.dataSource = self
        collectV.isScrollEnabled = false
        collectV.register(XLSearchHistoryCollectionViewCell.self, forCellWithReuseIdentifier: "XLSearchHistoryCollectionViewCell")
        collectV.backgroundColor = CViewBGColor
        return collectV
    }()
    lazy var historyCollectionViewFlowLayout: UICollectionViewFlowLayout = {
        let layout = UICollectionViewFlowLayout.init()
        layout.itemSize = CGSize(width: cellWidth, height: 34)
        layout.minimumLineSpacing = 0
        layout.minimumInteritemSpacing = 0
        layout.scrollDirection = .vertical
        layout.sectionInset = UIEdgeInsets.init(top: 0, left: 0, bottom: 0, right: 0)
        return layout
    }()
    func createUI() {
        view.addSubview(searchHeaderView)
        view.addSubview(historyLabel)
        view.addSubview(clearBut)
        view.addSubview(historyCollectionView)
        
        searchHeaderView.snp.makeConstraints { make in
            make.left.top.right.equalTo(self.view)
            make.height.equalTo(StatusBarHeight + 56)
        }
        historyLabel.snp.makeConstraints { make in
            make.left.equalTo(15)
            make.top.equalTo(searchHeaderView.snp.bottom).offset(15)
        }
        clearBut.snp.makeConstraints { make in
            make.centerY.equalTo(historyLabel)
            make.right.equalTo(-15)
            make.width.height.equalTo(20)
        }
        historyCollectionView.snp.makeConstraints { make in
            make.left.equalTo(0)
            make.right.equalTo(0)
            make.top.equalTo(historyLabel.snp.bottom).offset(12)
            make.height.equalTo(136)
        }
        
    }
    func viewBlocks() {
        
    }
    @objc func clearAction() {
        XLAlertTool.showAlert(title: "您确定清空搜索历史?", messgae: "", items: ["取消", "确定"], haveCancel: false) {[weak self] (str, index) in
            if index == 1 {
                let cache = YYCache.init(name: NSCacheModuleKeys.searchHistory_info.rawValue)
                cache?.removeObject(forKey: self?.cacheName ?? "")
                self?.historyArr = []
                self?.historyCollectionView.reloadData()
            }
        }
        
    }
    //获取本地历史数据
    func getSearchHistory() {
        //获取搜索历史cache
        let cache = YYCache.init(name: NSCacheModuleKeys.searchHistory_info.rawValue)
        //获取搜索历史与wiki相关cache
        historyArr = cache?.object(forKey: cacheName) as? Array ?? []
    }
    //处理本地缓存历史记录
    func saveSearchHistory(searchStr:String) {
        //获取搜索历史cache
        let cache = YYCache.init(name: NSCacheModuleKeys.searchHistory_info.rawValue)
        //删除历史数据有该数据的记录
        historyArr.removeAll(where: {$0 == searchStr})
        //将搜索记录插入第一个下标位置
        historyArr.insert(searchStr, at: 0)
        //若大于8个记录,删除最后一个
        if historyArr.count > 8 {
            historyArr.removeLast()
        }
        cache?.setObject(historyArr as NSCoding, forKey: cacheName)
        self.historyCollectionView.reloadData()
    }
}

extension XLSearchViewController:UICollectionViewDelegate,UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return historyArr.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell:XLSearchHistoryCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "XLSearchHistoryCollectionViewCell", for: indexPath) as! XLSearchHistoryCollectionViewCell
        cell.textLabel.text = historyArr[indexPath.row]
        cell.lineLabel.isHidden = indexPath.row%2 == 0
        return cell
    }
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        searchHeaderView.searchTextField.text = historyArr[indexPath.row]
        if let block = searchHeaderView.searchCompletion {
            block(historyArr[indexPath.row])
        }
        searchHeaderView.searchTextField.resignFirstResponder()
    }
    
}

XLSearchHistoryCollectionViewCell.swift

import UIKit

class XLSearchHistoryCollectionViewCell: UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.createUI()
    }
    func createUI() {
        self.backgroundColor = CViewBGColor
        self.contentView.addSubview(textLabel)
        self.contentView.addSubview(lineLabel)

        textLabel.snp.makeConstraints { make in
            make.top.right.bottom.equalTo(self.contentView)
            make.left.equalTo(lineLabel.snp.right).offset(15)
        }
        lineLabel.snp.makeConstraints { make in
            make.centerY.left.equalTo(self.contentView)
            make.width.equalTo(1)
            make.height.equalTo(10)
        }

    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    lazy var backView: UIView = {
        let view = UIView()
        view.backgroundColor = CSystemMsgBGColor
        view.alpha = 0.2
        return view
    }()

    lazy var textLabel: UILabel = {
        let label = UILabel.labelWithTitle(text: nil,
                                           textColor: CTextMainColor,
                                           textFont: 16,
                                           textAlignment: .left, specialFont: nil)
        return label
    }()
    lazy var lineLabel: UILabel = {
        let label = UILabel.labelWithTitle(text: nil,
                                           textColor: CTextMainColor,
                                           textFont: 16,
                                           textAlignment: .left, specialFont: nil)
        label.backgroundColor = CSeparator2Color
        return label
    }()

}

XLSearchHeaderView.swift

import UIKit

class XLSearchHeaderView: UIView {
    var placeholderStr :String?
    
    var cancelSearchCompletion: (() -> ())?
    
    var clearSearchStrCompletion: (() -> ())?
    
    var searchCompletion: ((_ text:String) -> ())?
    
    deinit {
        
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    init(placehoder:String) {
        self.init()
        self.placeholderStr = placehoder
        self.setupSubview()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    func setupSubview() {
        
        addSubview(searchTextView)
        searchTextView.addSubview(iconImageView)
        searchTextView.addSubview(searchTextField)
        addSubview(cancelBut)
        searchTextView.snp.makeConstraints { make in
            make.left.equalTo(10)
            make.right.equalTo(-52)
            make.height.equalTo(40)
            make.centerY.equalTo(cancelBut)
        }
        iconImageView.snp.makeConstraints { make in
            make.left.equalTo(18)
            make.width.height.equalTo(20)
            make.centerY.equalTo(searchTextView)
        }
        searchTextField.snp.makeConstraints { make in
            make.left.equalTo(iconImageView.snp.right).offset(12)
            make.centerY.equalTo(searchTextView)
            make.right.equalTo(searchTextView.snp.right).offset(-18)
        }

        cancelBut.snp.makeConstraints { make in
            make.right.equalTo(-10)
            make.top.equalTo(StatusBarHeight + 19)
            make.width.equalTo(32)
            make.height.equalTo(22)
        }

    }
    
    lazy var searchTextView:UIView = {
        let view = UIView()
        view.backgroundColor = .white
        view.layer.masksToBounds = true
        view.layer.cornerRadius = 20
        return view
    }()
    lazy var iconImageView:UIImageView = {
        let view = UIImageView()
        view.image = R.image.wiki_search()
        return view
    }()
    lazy var searchTextField:UITextField = {
        let textField = UITextField()
        textField.placeholder = placeholderStr
        textField.font = UIFont.normalFont(fontSize: 16)
        textField.textColor = CTextMainColor
        textField.delegate = self
        textField.returnKeyType = .search
        textField.clearButtonMode = .whileEditing
        textField.addTarget(self, action: #selector(changeText(_:)), for: .editingChanged)
        return textField
    }()

    lazy var cancelBut: UIButton = {
        let but = UIButton.buttonWithTitle(title: "取消", titleFont: 16, normalTitleColor: CTextMainColor, backgroundColor: nil)
        but.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)
        return but
    }()

    @objc func cancelAction() {
        self.cancelSearchCompletion != nil ? self.cancelSearchCompletion!() : nil
    }
}

extension XLSearchHeaderView:UITextFieldDelegate {
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        guard textField.text?.count ?? 0 > 0 else {
            return true
        }
        if let block = searchCompletion {
            block(textField.text ?? "")
        }
        textField.resignFirstResponder()
        return true
    }
    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        self.clearSearchStrCompletion != nil ? self.clearSearchStrCompletion!() : nil
        return true
    }
    
    func textFieldDidBeginEditing(_ textField: UITextField) {
        self.searchTextField.perform(#selector(selectAll(_:)), with: nil, afterDelay: 0.0)
    }
    @objc func changeText(_ textField: UITextField) {
        guard textField.text?.count ?? 0 > 0 else {
            self.clearSearchStrCompletion != nil ? self.clearSearchStrCompletion!() : nil
            return
        }
        let range = textField.markedTextRange
        if range == nil {
            if let block = searchCompletion {
                block(textField.text ?? "")
            }
        }
        
    }

}

以下为引用
XLSearchWikiViewController.swift

import UIKit

class XLSearchWikiViewController: XLSearchViewController,PushWebProtocol {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }
    
    required init(params: Dictionary?) {
        super.init(params: nil)
        placehoder = "请输入文章标题"
        searchType = .healthyWiki
        cacheName = NSCacheModuleKeys.searchHistory_wiki_info.rawValue
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewBlocks() {
        //取消
        searchHeaderView.cancelSearchCompletion = {[weak self] in
            self?.navigationController?.popViewController(animated: false)
        }
        //clear
        searchHeaderView.clearSearchStrCompletion = {[weak self] in
            self?.viewModel.dataArray = []
            self?.tableView.reloadData()
            self?.searchViewStyle(isSearching: false)
        }
        //搜索
        searchHeaderView.searchCompletion = {[weak self] searchStr in
            
            //保存历史记录
            self?.saveSearchHistory(searchStr: searchStr)
            //调接口获取数据
            self?.viewModel.getWikiSearchData(searchStr: searchStr)
        }
        viewModel.reloadDataSuccess = {[weak self] in
            self?.searchViewStyle(isSearching: true)
            
            if (self?.viewModel.dataArray.isEmpty)! {
                self?.tableView.emptyView = XLEmptyView.init(type: .wiki_search_empty, offset: -150, tapClosure: { [weak self] in
                    self?.searchHeaderView.searchTextField.resignFirstResponder()
                    self?.viewModel.getWikiSearchData(searchStr: self?.searchHeaderView.searchTextField.text ?? "")
                })
            }
            self?.tableView.reloadData()
        }
    }
    
    private lazy var tableView: UITableView = {
        let tableView = UITableView.init(delegate: self, dataSource: self)
        tableView.mj_header = viewModel.headerRefresh
        tableView.mj_footer = viewModel.footerRefresh
        tableView.backgroundColor = .clear
        
        return tableView
    }()
    lazy var viewModel: XLHealthyWikiViewModel = {
        let model = XLHealthyWikiViewModel.init()
        return model
    }()
    func setupUI() {
        view.addSubview(tableView)
        self.tableView.frame = CGRect.zero
    }
    //当前页面状态ture:搜索结果;false:未开始搜索
    func searchViewStyle(isSearching:Bool) {
        self.historyLabel.isHidden = isSearching
        self.clearBut.isHidden = isSearching
        self.historyCollectionView.isHidden = isSearching
        self.tableView.isHidden = !isSearching
        if isSearching {
            tableView.snp.updateConstraints { make in
                make.top.equalTo(searchHeaderView.snp.bottom).offset(6)
                make.left.right.bottom.equalTo(view)
            }
        } else {
            self.tableView.frame = CGRect.zero
        }
    }
}
//MARK: - UITableViewDelegate
extension XLSearchWikiViewController: UITableViewDelegate,UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return viewModel.dataArray.count
    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        UITableView.automaticDimension
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let model = viewModel.dataArray[indexPath.row]
        let searchStr = searchHeaderView.searchTextField.text ?? ""
        let cell = XLWikiSearchTableViewCell.cell(of: tableView, indexPath, viewModel.dataArray[indexPath.row])
        cell.titleLabel.attributedText = model?.title?.m_setKeyColorAll(keyString: [searchStr], keyColor: CRedTipColor)
        return cell
    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        saveSearchHistory(searchStr: searchHeaderView.searchTextField.text ?? "")
        let model = viewModel.dataArray[indexPath.row]
        self.pushWeb(url: model?.wiki_h5_url ?? "", type: XLWebType.wikiDetail, para: nil)
    }
}

你可能感兴趣的:(搜索VC实例(本地历史记录))