需求说明
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": "软件简介:
比邻是一款电话社交平台APP,是一个刺激年轻人心跳的社交工具。
主要通过即时通话,随时畅聊你感兴趣的话题,并且可以通过精彩的图片和文字分享生活中的美好点滴,
也可以欣赏其它用户个性十足的个人资料和生活相册。
功能简介:
√随机电话 - 无距离、无时差随时开聊
√超能力标签 - 找到自己的独特话题
√最近在线 - 温暖的陌生人都在这里
√连线好友 - 免费无限时、无限次通话
使用场景:
√当你寂寞的时候,打打比邻,这里有人为你唱歌
√当你失眠的时候,打打比邻,这里有人哄你入睡
√当你难过的时候,打打比邻,这里有人逗你开心
√当你觉得冷的时候,打打比邻,这里有暖男热线
更新内容:
1、解决部分崩溃问题2、优化随机群聊匹配",
"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..
修改该属性则会延迟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。不会重新创建,因此每次需要初始化。