我想搜索我的plist项目。 plist由一系列字典组成。每个键/值代表字符串/ Ints等,但这并不重要。
正如您在下面的tableViewController类中看到的,我目前有一个我输入的数组。我知道我需要从我的plist中创建一个对象/项目数组,但我无法弄清楚如何在视图控制器中引用plist中的对象。
查看controller.swift文件:
import UIKit
class TableViewController: UITableViewController, UISearchResultsUpdating {
var array = ["Example 1", "Example 2", "Example 3"]
var filteredArray = [String]()
var searchController = UISearchController()
var resultsController = UITableViewController()
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: resultsController)
tableView.tableHeaderView = searchController.searchBar
searchController.searchResultsUpdater = self
resultsController.tableView.delegate = self
resultsController.tableView.dataSource = self
}
//Added func to update search results
func updateSearchResults(for searchController: UISearchController) {
filteredArray = array.filter({ (array:String) -> Bool in
if array.contains(searchController.searchBar.text!) {
return true
} else {
return false
}
})
resultsController.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension TableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == resultsController.tableView {
return filteredArray.count
} else {
return array.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
if tableView == resultsController.tableView {
cell.textLabel?.text = filteredArray[indexPath.row]
} else {
cell.textLabel?.text = array[indexPath.row]
}
return cell
}
}
我试过通过从plists教程创建一个对象类来解决这个问题。它使用了元素周期表的例子:
import UIKit
struct Element {
enum State: String {
case Solid, Liquid, Gas
}
let atomicNumber: Int
let atomicWeight: Float
let discoveryYear: String
let group: Int
let name: String
let period: Int
let radioactive: Bool
let state: State
let symbol: String
// Position in the table
let horizPos: Int
let vertPos: Int
}
extension Element {
enum ErrorType: Error {
case noPlistFile
case cannotReadFile
}
/// Load all the elements from the plist file
static func loadFromPlist() throws -> [Element] {
// First we need to find the plist
guard let file = Bundle.main.path(forResource: "Element", ofType: "plist") else {
throw ErrorType.noPlistFile
}
// Then we read it as an array of dict
guard let array = NSArray(contentsOfFile: file) as? [[String: AnyObject]] else {
throw ErrorType.cannotReadFile
}
// Initialize the array
var elements: [Element] = []
// For each dictionary
for dict in array {
// We implement the element
let element = Element.from(dict: dict)
// And add it to the array
elements.append(element)
}
// Return all elements
return elements
}
/// Create an element corresponding to the given dict
static func from(dict: [String: AnyObject]) -> Element {
let atomicNumber = dict["atomicNumber"] as! Int
let atomicWeight = Float(dict["atomicWeight"] as! String) ?? 0
let discoveryYear = dict["discoveryYear"] as! String
let group = dict["group"] as! Int
let name = dict["name"] as! String
let period = dict["period"] as! Int
let radioactive = dict["radioactive"] as! String == "True"
let state = State(rawValue: dict["state"] as! String)!
let symbol = dict["symbol"] as! String
let horizPos = dict["horizPos"] as! Int
let vertPos = dict["vertPos"] as! Int
return Element(atomicNumber: atomicNumber,
atomicWeight: atomicWeight,
discoveryYear: discoveryYear,
group: group,
name: name,
period: period,
radioactive: radioactive,
state: state,
symbol: symbol,
horizPos: horizPos,
vertPos: vertPos)
}
}
在viewController类中,而不是
var array = ["Example 1", "Example 2", "Example 3"]
我尝试了各种
var array = Element["name"]
和
var array = elements.name
但是它们显然不起作用,因为对plist的引用是在对象类中。
如果有人对如何使用swift 3 / xcode 8解决这个问题有任何想法,我会非常感激!!
答案 0 :(得分:0)
我希望你的问题仍然有用。据我了解,你不能过滤你的阵列,对吗?如果是这样,我建议您查看this和this教程。它们都代表了加载过滤数组的一些不同方法,但它们并不重要,它们可以工作。
P.S。如果你想在以后定制它,我不建议你制作一个特殊的tableView进行搜索,因为你必须稍后以编程方式进行。 这样做会更有效率:
If searchController.isActive {
// do some stuff
} else { // another stuff }
但这只是我的观点。我希望我的问题会有所帮助;)。
答案 1 :(得分:0)
感谢Oleg的链接。他们真的很棒!!
我遇到的问题不是过滤,而是实际将我的plist中的对象解析为tableview。我花了几天时间才找到答案,以防其他人也遇到同样的问题。请记住,我是相当新的,所以它可能不是最佳/完美的方式,但它的工作原理。
在viewDidLoad中,我使用以下代码引用了plist:
let path = Bundle.main.path(forResource: "Elements", ofType: "plist")
let dictArray = NSArray(contentsOfFile: path!)
我不确定相关性,但我很确定如果需要更新plist,则需要下一位。 (也在viewDidLoad中)
for elementItem in dictArray! {
let newElement : Element = Element(state:((elementItem as AnyObject).object(forKey: "state")) as! String,
atomicNumber:((elementItem as AnyObject).object(forKey: "atomicNumber")) as! Int,
atomicWeight:((elementItem as AnyObject).object(forKey: "atomicWeight")) as! Float,
discoveryYear:((elementItem as AnyObject).object(forKey: "discoveryYear")) as! String
等。对于字典中的每个键,其顺序与问题中的Element对象相同。然后(也在viewDidLoad中):
elementsArray.append(newElement)
然后它非常简单,在cellForRow中我只需要创建一个引用该对象的新变量,我可以调用每个/任何相关的字典键。 E.g:
let element : Element
cell.textLabel!.text = element.name
cell.detailTextLabel?.text = element.symbol
return cell
像我说的那样,我知道它并不完美,但它对我有用。我听说不是在viewDidLoad中放入太多信息的最佳做法,所以其他人可能能够确认或提供更好的答案。