美文网首页
[技术文档][技术中心][iOS部][114啦]全局搜索

[技术文档][技术中心][iOS部][114啦]全局搜索

作者: Zongzi_599 | 来源:发表于2017-11-30 15:12 被阅读0次

    需求说明

    1、首页进入显示搜索历史,网页进入对关键词进行联想搜索。
    2、搜索需要用web打开都统一新建标签页打开,加在最后面。
    3、按照标签、工具、应用、经验、说明书、百度联想排序。
    4、显示1条工具,点击更多显示工具列表。
    5、显示3条相关的经验,点击更多进入更多经验列表。
    6、显示3条相关的说明书,点击更多进入更多相关说明书的列表。
    7、关键词联想,由百度提供该关键词的联想,并显示在底部。

    需求地址

    http://192.168.1.75/114la/220/114la_220/#g=1&p=2_2_%E6%90%9C%E7%B4%A2_%E6%B5%8F%E8%A7%88%E4%BA%A4%E4%BA%92

    接口说明

    URL:http://114larc.com/q/api/1.0/android/1.0/search
    请求方式:GET

    • 请求参数说明:
    参数名称 必选 类型 描述
    q true string 关键字
    • 返回结果说明:
      列表中的type值:1-经验 2-说明书 3-工具 4-标签 5-应用,
      不同type对应不同的结构模型,经验和说明书结构一样,请参考下面的json数据结构:
      share:分享地址

    • 返回结果:

    {
        "state": 1,
        "code": 0,
        "message": "",
        "data": {
            "share": "114larc.com/p/search?q=1",
            "list": [
                {
                    "name": "标签",
                    "type": 4,
                    "list": [
                        "比较"
                    ]
                },
                {
                    "name": "工具",
                    "type": 3,
                    "list": [
                        {
                            "name": "比较6",
                            "url": "http://6.com",
                            "logo": "http://img.114larc.com/thumb/P/RC/3D/PRC3D74AC06B2B5772DF7ED285C6C31F5B0_100_100?s=6dt6DCcT4y78R5jmWyrsjQ"
                        }
                    ]
                },
                {
                    "name": "应用",
                    "type": 5,
                    "list": [
                        {
                            "pinyin": "bilin-402anzhuoyingyongapk",
                            "size": "31.1M",
                            "name": "比邻",
                            "description": "<p style=\"text-indent: 2em;\">软件简介:</p><p style=\"text-indent: 2em;\">比邻是一款<strong>电话社交</strong>平台APP,是一个刺激年轻人心跳的社交工具。</p><p style=\"text-indent: 2em;\">主要通过<strong>即时通话</strong>,随时畅聊你<strong>感兴趣</strong>的话题,并且可以通过精彩的图片和文字<strong>分享</strong>生活中的美好点滴,</p><p style=\"text-indent: 2em;\">也可以<strong>欣赏</strong>其它用户个性十足的个人资料和生活相册。</p><hr k_oof_k=\"line\" style=\"border-width: 1px 0px 0px; border-right-style: initial; border-bottom-style: initial; border-left-style: initial; border-right-color: initial; border-bottom-color: initial; border-left-color: initial; border-image: initial; border-top-style: dashed; border-top-color: rgb(204, 204, 204); height: 0px; overflow: hidden;\"><p style=\"text-indent: 2em;\">功能简介:</p><p style=\"text-indent: 2em;\">√<strong>随机电话</strong> - 无距离、无时差随时开聊</p><p style=\"text-indent: 2em;\">√<strong>超能力标签</strong> - 找到自己的独特话题</p><p style=\"text-indent: 2em;\">√<strong>最近在线</strong> - 温暖的陌生人都在这里</p><p style=\"text-indent: 2em;\">√<strong>连线好友</strong> - 免费无限时、无限次通话</p><hr k_oof_k=\"line\" style=\"border-width: 1px 0px 0px; border-right-style: initial; border-bottom-style: initial; border-left-style: initial; border-right-color: initial; border-bottom-color: initial; border-left-color: initial; border-image: initial; border-top-style: dashed; border-top-color: rgb(204, 204, 204); height: 0px; overflow: hidden;\"><p style=\"text-indent: 2em;\">使用场景:</p><p style=\"text-indent: 2em;\">√当你<strong>寂寞</strong>的时候,打打比邻,这里有人为你唱歌</p><p style=\"text-indent: 2em;\">√当你<strong>失眠</strong>的时候,打打比邻,这里有人哄你入睡</p><p style=\"text-indent: 2em;\">√当你<strong>难过</strong>的时候,打打比邻,这里有人逗你开心</p><p style=\"text-indent: 2em;\">√当你觉得<strong>冷</strong>的时候,打打比邻,这里有暖男热线</p><hr k_oof_k=\"line\" style=\"border-width: 1px 0px 0px; border-right-style: initial; border-bottom-style: initial; border-left-style: initial; border-right-color: initial; border-bottom-color: initial; border-left-color: initial; border-image: initial; border-top-style: dashed; border-top-color: rgb(204, 204, 204); height: 0px; overflow: hidden;\"><p style=\"text-indent: 2em;\">更新内容:</p><div style=\"text-indent: 2em;\">1、解决部分崩溃问题</div><div style=\"text-indent: 2em;\">2、优化随机群聊匹配</div>",
                            "logo": "http://img.anxia.com/thumb/P/DL/BB/PDLBB6E146E341F7900B35E690F7813E1B3_0?s=Sv8uwHljz5_qEeEM9hq7nA",
                            "sid": "18081",
                            "release_time": "1496073600",
                            "has_history": 0,
                            "url": "/a/bilin-402anzhuoyingyongapk"
                        }
                    ]
                },
                {
                    "name": "说明书",
                    "type": 2,
                    "list": [
                        {
                            "t_id": 90,
                            "c_id": 4362,
                            "type": 2,
                            "is_hot": 0,
                            "is_top": 0,
                            "subject": "苯巴比妥片",
                            "summary": "",
                            "state": 1,
                            "post_time": 1500968344,
                            "update_time": 1500982779,
                            "url": "http://114larc.com/s/detail/23D60020000004Y5BJDPASGK.html",
                            "cat_id": 0,
                            "useful_num": 0,
                            "is_useful": 0,
                            "location": "",
                            "icon_url": "http://img.114larc.com/thumb/P/RC/2D/PRC2D0CF8CCC0AAC491D879969C5B4BF3AD_800_800?s=TRfGkLQUmrIzy_5wETifbA",
                            "pics": [],
                            "tags": [
                                "失眠",
                                "心脑血管"
                            ]
                        }
                    ]
                }
            ],
            "count": 4
        }
    }
    

    核心代码

    进入搜索界面都先调用该方法,进行初始化操作

    func urlBarViewDidClick(_ urlBarView: URLBarView) {
            if let keyworkSearch = MainViewFacade.sharedInstance.cache?.object(forKey: "keywork_search") as? [NSCoding] {
                let temp = NSMutableArray(array: keyworkSearch)
                //覆盖安装时,缓存的内容为【string】,需转化为模型
                if temp as AnyObject is [String] {
                    for i in 0..<temp.count {
                        temp.replaceObject(at: i, with: SearchCellModel(keyword: temp[i] as? String ?? ""))
                    }
                }
                if !isEqualContains(self.keyworkSearch, other: temp as AnyObject as? [SearchCellModel] ?? []) {
                    self.keyworkSearch = temp as AnyObject as? [SearchCellModel] ?? []
                }
            }
    
            //文字修改
            changeUrlBarViewText()
    
            if self.contenView.superview == nil {
                self.addContenView()
                if urlBarView.addressTextField.text?.isEmpty == false {
                    self.datas = []
                }
                shouldUpdateDatas = true
            } else {
                ////已经在搜索界面点击。成为焦点
                shouldUpdateDatas = false
            }
            
            textFieldText = urlBarView.addressTextField.text
            self.tableView.reloadData()
        }
    

    修改该属性则会延迟0.6s执行搜索操作,还带有cancel上一次未完成的请求。

    var textFieldText: String? {
            didSet {
                
                if textFieldText?.characters.count == 0 && shouldUpdateDatas {
                    NSObject.cancelPreviousPerformRequests(withTarget: self)
                    updateDatas("")
                    return
                }
                guard textFieldText != oldValue else {
                    if shouldUpdateDatas {
                        NSObject.cancelPreviousPerformRequests(withTarget: self)
                        self.perform(#selector(NewSearchViewManager.updateDatas(_:)), with:textFieldText, afterDelay: 0.1)
                        shouldUpdateDatas = false
                    }
                    return
                }
    
                NSObject.cancelPreviousPerformRequests(withTarget: self)
                self.perform(#selector(NewSearchViewManager.updateDatas(_:)), with:textFieldText, afterDelay: 0.6)
            }
        }
    
    

    该方法则是真正发出请求。
    该处分为两个接口,同时发出请求,先回来数据则先显示,后回来的则进行处理拼接起来后再刷新数据。
    返回的结果是有固定的排序方式的。

    func updateDatas(_ text: String?) {
            if text?.trimmingCharacters(in: CharacterSet.whitespaces).isEmpty == false {
                
                let enginModel = SearchGroupModel(SearchGroupType.engine)
                enginModel.searchDatas = [SearchCellModel(keyword: text!)]
                self.datas = [enginModel]
                self.tableView.reloadData()
                //114啦  热词联想搜索接口
                self.api.associateSearch(withKeywork: text!) { [weak self](keyworks, searchEngineURL) -> Void in
                    guard let strongSelf = self else {
                        return
                    }
                    guard let keyworks = keyworks as? [String], strongSelf.textFieldText! == text else {
                        return
                    }
                    
                    var levdatas = [SearchCellModel]()
                    
                    for kword in keyworks {
                        let model = SearchCellModel(keyword: kword)
                        levdatas.append(model)
                    }
                    
                    if levdatas.count > 0 || text == "114la.com" || text == "115.com" {
                        if text == "w" || text == "ww" || text == "www" || text == "www."
                         || text == "114la.com" || text == "115.com" {
                            levdatas.insert(SearchCellModel(keyword: "www.115.com"), at: 0)
                            levdatas.insert(SearchCellModel(keyword: "www.114la.com"), at: 0)
                        }
                        let lenovoModel = SearchGroupModel(SearchGroupType.lenovo)
                        lenovoModel.searchDatas = levdatas
                        
                        
                        if let datas = strongSelf.datas, datas.last?.type == .share {
                            strongSelf.datas?.insert(lenovoModel, at: datas.count - 1)
                        } else {
                            strongSelf.datas?.append(lenovoModel)
                        }
                    }
                    strongSelf.tableView.isHidden = false
                    strongSelf.tableView.dk_backgroundColorPicker = DKColor.picker(withNormalColor: UIConstants.NormalBackgroundColor, nightColor: UIConstants.NightDarkBackgroundColor)
                    strongSelf.tableView.reloadData()
                }
                
                // 综合搜索
                YYW114LaService.comprehensiveSearch(keyword: text!, { (json, error) -> AnyObject? in
                    if error != nil {
                        self.urlBarView?.addressTextField.resignFirstResponder()
                        return nil
                    }
                    if let json = json {
                        guard self.textFieldText! == text, json["state"].intValue == 1 else {
                            return nil
                        }
                        
                        let listDatas = json["data"]["list"].arrayValue
                        
                        var tempDatas = [SearchGroupModel]()
                    
                        for type in showOrder {
                            if let dict = listDatas.filter({ (dict) -> Bool in
                                return dict["type"].intValue == type
                            }).first {
                                switch type {
                                case 1:
                                    if dict["list"].arrayValue.count > 0 {
                                        tempDatas.append(SearchGroupModel(SearchGroupType.experience,dict["list"].arrayValue))
                                    }
                                case 2:
                                    if dict["list"].arrayValue.count > 0 {
                                        tempDatas.append(SearchGroupModel(SearchGroupType.instructions,dict["list"].arrayValue))
                                    }
                                case 3:
                                    if dict["list"].arrayValue.count > 0 {
                                        tempDatas.append(SearchGroupModel(SearchGroupType.tool,dict["list"].arrayValue))
                                    }
                                case 4:
                                    if dict["list"].arrayValue.count > 0 {
                                        let model = SearchGroupModel(.label)
                                        model.searchDatas = SearchGroupModel.getLabelModels(dict["list"].arrayValue)
                                        tempDatas.append(model)
                                    }
                                case 5:
                                    if dict["list"].arrayValue.count > 0 {
                                        tempDatas.append(SearchGroupModel(SearchGroupType.application,dict["list"].arrayValue))
                                    }
                                case 999:
                                    tempDatas.append(SearchGroupModel(SearchGroupType.ads,[dict["list"]]))
                                default:
                                    break
                                }
                            }
                        }
                        
                        self.datas?.insert(contentsOf: tempDatas, at: 1)
                        if !json["data"]["share"].stringValue.isEmpty && tempDatas.count > 0
                        && self.datas?.last?.type != .share {
                            let shareModel = SearchGroupModel(SearchGroupType.share)
                            shareModel.searchDatas = [SearchCellModel(keyword: json["data"]["share"].stringValue)]
                            self.datas?.append(shareModel)
                        }
                        
                        self.tableView.dk_backgroundColorPicker = DKColor.picker(withNormalColor: UIConstants.NormalBackgroundColor, nightColor: UIConstants.NightDarkBackgroundColor)
                        self.tableView.isHidden = false
                        self.tableView.reloadData()
                    }
                    return nil
                })
            }
            else
            {
                shouldShowKeyWordSearch()
            }
        }
    

    当点击搜索记录发生页面跳转,并且会记录搜索历史。

    //处理url后进行加载
    fileprivate func loadAndAddToHistoryWithURLString(_ URLString: String) {
            
            guard !isSearchUrlToChangeSearchKey(URLString) else { return }
            
            var text = self.searchEngineURL + URLString
            if let _ = MainViewFacade.sharedInstance.mainViewModel.verificationURL(URLString)
            {
                text = URLString
            }
            
            if UserDefaults.standard.bool(forKey: "isOpenSearch")
            {
                self.addKeyworkToSearchHistory(URLString)
            }
            
            if let request = MainViewFacade.sharedInstance.mainViewModel.verificationURL(text) {
                urlBarView?.clearText(UITapGestureRecognizer())
                urlBarView?.cancel()
    //            MainViewFacade.sharedInstance.currentPageView().loadRequest(request)
                mainViewController()?.pageViewManager.newTabLoadRequest(request)
                if let absoluteString = request.url?.absoluteString {
                    urlBarView?.addressTextString = absoluteString
                }
                cancelFocus()
            }
            
        }
    //添加搜索历史记录 隐身模式不添加
        func addKeyworkToSearchHistory(_ keywork: String) {
            guard !self.isPrivate else {
                return
            }
            let index = isContainsKeyWord(keywork)
            if index >= 0 {
                self.keyworkSearch.remove(at: index)
            }
            let searchModel:SearchCellModel
            
            if let _ = MainViewFacade.sharedInstance.mainViewModel.verificationURL(keywork) {
                searchModel = SearchCellModel(dict: ["keyWord": keywork as AnyObject], type: .url)
            } else {
                searchModel = SearchCellModel(keyword: keywork)
            }
            
            self.keyworkSearch.insert(searchModel, at: 0)
            if self.keyworkSearch.count > 10 {
                self.keyworkSearch.removeSubrange(Range(10 ..< self.keyworkSearch.count))
            }
            MainViewFacade.sharedInstance.cache?.setObject(self.keyworkSearch as NSCoding, forKey: "keywork_search")
        }
    

    添加分享搜索结果以后需要判断是不是打开分享出去的搜索结果url。
    是的话则用原生UI打开搜索页面,不进行打开网页。

    fileprivate func isSearchUrlToChangeSearchKey(_ text: String) -> Bool {//http://114larc.com/p/search?q=keyword
            if text.contains("114larc.com/p/search?q=") || text.contains("114la.com/p/search?q=") {
                let range = text.range(of: ".com/p/search?q=")
                var changeText = text.substring(from: range!.upperBound)
                changeText = changeText.removingPercentEncoding ?? changeText
                urlBarView?.addressTextField.text = changeText
                textFieldText = changeText
                return true
            }
            return false
        }
    

    该搜索界面是将view添加在首页的view中的,显示时添加,取消搜索时将view移除。
    使用的是同一个tableview。不会重新创建,因此每次需要初始化。

    相关文章

      网友评论

          本文标题:[技术文档][技术中心][iOS部][114啦]全局搜索

          本文链接:https://www.haomeiwen.com/subject/sxpvbxtx.html