我试图让搜索结果显示在tableView上。我相信我已正确解析了JSON,唯一的问题是结果不会显示在我的tableView上。
以下是代码:
var searchText : String! {
didSet {
getSearchResults(searchText)
}
}
var itemsArray = [[String:AnyObject]]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.reloadData()
}
// MARK: - Get data
func getSearchResults(text: String) {
if let excapedText = text.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) {
Alamofire.request(.GET, "https://api.duckduckgo.com/?q=\(excapedText)&format=json")
.responseJSON { response in
guard response.result.error == nil else {
// got an error in getting the data, need to handle it
print("error \(response.result.error!)")
return
}
let items = JSON(response.result.value!)
if let relatedTopics = items["RelatedTopics"].arrayObject {
self.itemsArray = relatedTopics as! [[String:AnyObject]]
}
if self.itemsArray.count > 0 {
self.tableView.reloadData()
}
}
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6 // itemsArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SearchResultCell", forIndexPath: indexPath) as! SearchResultCell
if itemsArray.count > 0 {
var dict = itemsArray[indexPath.row]
cell.resultLabel?.text = dict["Text"] as? String
} else {
print("Results not loaded yet")
}
return cell
}
如果我有一个静态API请求,我认为这段代码可以正常工作,因为我可以在viewDidLoad中获取并避免大量的.isEmpty
检查。
当我运行该程序时,我得到6 Results not loaded yet
(来自print
中的cellForRowAtIndexPath
)。
当完成处理程序被调用response in
时,它会下降到self.items.count > 3
(通过),然后点击self.tableView.reloadData()
,它什么都不做(我通过在它上面放置一个断点来检查)。 / p>
我的代码有什么问题?
修改
if self.itemsArray.count > 0 {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
}
试过这个但是,即使在调用alamofire hander之前重新加载了6次,tableView仍然没有重新加载...
这是一件奇怪的事情,显然在被称为“itemsArray.count
”之前,我的Results not loaded yet
将为0,这就是为什么我得到numberOfRowsInSection
。我弄清楚为什么它会重复6次;我将其设置为dict["Text"]
...所以@Rob,我无法检查cell.resultLabel?.text
或SearchResultCell
,因为它们永远不会被调用。 "文本"这是正确的,这里是JSON的链接:http://api.duckduckgo.com/?q=DuckDuckGo&format=json&pretty=1
此外,我确实将标签链接到自定义单元格类bookshelf.transaction(function (t) {
return User.forge(data) // here
.save(null, { transacting: t })
.then(function (user){
return Room.forge({ userId: user.id })
.save(null, { transacting: t });
})
})
最后,我得到了明显的结果。
答案 0 :(得分:4)
两个问题。
一个问题是prepareForSegue
:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let searchResultTVC = SearchResultsTVC()
searchResultTVC.searchText = searchField.text
}
这不是使用已经实例化的“目标”视图控制器,而是创建第二个SearchResultsTVC
,设置其searchText
,然后让它超出范围并被取消分配,丢失搜索这个过程中的文字。
相反,你想要:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let searchResultTVC = segue.destinationViewController as? SearchResultsTVC {
searchResultTVC.searchText = searchField.text
}
}
您不应该依赖目标视图控制器中的didSet
来触发搜索,因为在表视图被实例化之前,该属性是由源视图控制器设置的。在视图加载(viewDidLoad
)之前,您不希望启动搜索。
我建议更换didSet
逻辑,然后在viewDidLoad
的{{1}}中执行搜索。
我原来的答案,讨论原始问题中提供的代码如下。
-
我使用了问题中最初提供的代码并且工作正常。就个人而言,我可能会进一步简化:
消除了SearchResultsTVC
中硬编码“6”的删除,因为这会在控制台中给出误报错误;
逃脱的百分比不太正确(某些角色会滑过,未转义);而不是沉溺于自己做正确的方法,最好让Alamofire为你做这件事,使用numberOfRowsInSection
;
我个人消除了SwiftyJSON,因为它没有提供任何价值...... Alamofire已经为我们进行了JSON解析。
无论如何,我的简化版本如下:
parameters
当我这样做时,我得到了以下内容:
问题必须在其他地方休息。也许它在故事板中。也许是在class ViewController: UITableViewController {
var searchText : String!
override func viewDidLoad() {
super.viewDidLoad()
getSearchResults("DuckDuckGo")
}
var itemsArray: [[String:AnyObject]]?
func getSearchResults(text: String) {
let parameters = ["q": text, "format" : "json"]
Alamofire.request(.GET, "https://api.duckduckgo.com/", parameters: parameters)
.responseJSON { response in
guard response.result.error == nil else {
print("error \(response.result.error!)")
return
}
self.itemsArray = response.result.value?["RelatedTopics"] as? [[String:AnyObject]]
self.tableView.reloadData()
}
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemsArray?.count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SearchResultCell", forIndexPath: indexPath) as! SearchResultCell
let dict = itemsArray?[indexPath.row]
cell.resultLabel?.text = dict?["Text"] as? String
return cell
}
}
更新的代码中,您没有与我们共享(通过searchText
触发查询)。很难说。但它在您提供的代码段中似乎不是问题。
但是在进行调试时,请确保在第一次调用表视图委托方法时以及第二次调用时不会混淆(由didSet
块触发。通过消除responseJSON
中的硬编码“6”,可以减少一些误报。
答案 1 :(得分:0)
我认为你应该编辑:
func getSearchResults(text: String) {
if let excapedText = text.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) {
Alamofire.request(.GET, "https://api.duckduckgo.com/?q=\(excapedText)&format=json")
.responseJSON { response in
guard response.result.error == nil else {
// got an error in getting the data, need to handle it
print("error \(response.result.error!)")
return
}
let items = JSON(response.result.value!)
if let relatedTopics = items["RelatedTopics"].arrayObject {
self.itemsArray = relatedTopics as! [[String:AnyObject]]
// if have result data -> reload , & no if no
if self.itemsArray.count > 0 {
self.tableView.reloadData()
}
}else{
print("Results not loaded yet")
}
}
}
}
并且
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SearchResultCell", forIndexPath: indexPath) as! SearchResultCell
// i 'm sure: itemsArray.count > 0 in here if in numberOfRowsInSection return itemsArray.count
var dict = itemsArray[indexPath.row]
cell.resultLabel?.text = dict["Text"] as? String
return cell
}
你应该分享json结果(格式),在cellForRowAtIndexPath中打印dict,这样很容易获得帮助