来自plist的UISearchBar textDidChange数据

时间:2017-07-10 11:10:47

标签: swift uitableview plist uisearchbar

我想搜索我的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解决这个问题有任何想法,我会非常感激!!

2 个答案:

答案 0 :(得分:0)

我希望你的问题仍然有用。据我了解,你不能过滤你的阵列,对吗?如果是这样,我建议您查看thisthis教程。它们都代表了加载过滤数组的一些不同方法,但它们并不重要,它们可以工作。

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中放入太多信息的最佳做法,所以其他人可能能够确认或提供更好的答案。