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

效果图


搜索界面

XLSearchViewController.swift

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

    var cellWidth = SCREEN_WIDTH/2
    var historyArr : Array<String> = []
    
    //默认搜索健康百科
    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<String> ?? []
    }
    //处理本地缓存历史记录
    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<String, Any>?) {
        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)
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容