【发布时间】:2019-08-02 04:25:45
【问题描述】:
我正在尝试从我的表格视图中删除提醒,但是当它来自通过搜索栏过滤时,常规删除在没有发生过滤器时非常有效,但是当过滤器位于搜索栏中时,它会使应用程序崩溃.
这是代码;
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
var updatedArray = [Reminder]()
if editingStyle == .delete {
if filtered == false {
reminders.remove(at: indexPath.row)
tableReminders.deleteRows(at: [indexPath], with: .fade)
convertAndSaveInDDPath(array: reminders)
}
if filtered == true {
updatedArray = reminders.filter{ $0.reminderName != filterData[indexPath.row].reminderName}
print(updatedArray)
reminders = updatedArray
tableReminders.deleteRows(at: [indexPath], with: .fade)
tableReminders.reloadData()
//convertAndSaveInDDPath(array: reminders)
}
}
}
任何帮助将不胜感激,谢谢。
编辑(新代码):
public struct Reminder {
var reminderName : String
var reminderPriority : String
var reminderDate : Date
var reminderStatus : String
var reminderSavedTime : Date
}
var reminders : [Reminder] = []
var filtered : Bool = false
public func getFilePath(fileName:String) -> String {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
let filePath = url.appendingPathComponent(fileName)?.path
return filePath!
}
public func convertAndSaveInDDPath (array:[Reminder]) {
let objCArray = NSMutableArray()
for obj in array {
// we have to do something like this as we can't store struct objects directly in NSMutableArray
let dict = NSDictionary(objects: [obj.reminderName ,obj.reminderPriority, obj.reminderDate, obj.reminderStatus, obj.reminderSavedTime ], forKeys: ["reminderName" as NSCopying,"reminderPriority" as NSCopying, "reminderDate" as NSCopying, "reminderStatus" as NSCopying, "reminderSavedTime" as NSCopying])
objCArray.add(dict)
}
// this line will save the array in document directory path.
objCArray.write(toFile: getFilePath(fileName: "remindersArray"), atomically: true)
}
public func getArray() -> [Reminder]? {
var remindersArray = [Reminder]()
if let _ = FileManager.default.contents(atPath: getFilePath(fileName: "remindersArray")) {
let array = NSArray(contentsOfFile: getFilePath(fileName: "remindersArray"))
for (_,userObj) in array!.enumerated() {
let reminderDict = userObj as! NSDictionary
let reminder = Reminder(reminderName: (reminderDict.value(forKey: "reminderName") as? String)!, reminderPriority: (reminderDict.value(forKey: "reminderPriority") as? String)!, reminderDate: (reminderDict.value(forKey: "reminderDate") as? Date)!, reminderStatus: (reminderDict.value(forKey: "reminderStatus") as? String)!, reminderSavedTime: (reminderDict.value(forKey: "reminderSavedTime") as? Date)!)
remindersArray.append(reminder)
}
return remindersArray
}
return nil
}
class ViewController: UIViewController, UITableViewDataSource, UITextFieldDelegate, UITableViewDelegate, UISearchBarDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Reminder Section
return filteredReminder.count
}
@IBOutlet var searchBar: UISearchBar!
var filterData = [Reminder]()
var originalReminder = [Reminder]() // original data array.
var filteredReminder = [Reminder]() // data that used to show in tableview.
var sortedAZState : Bool = false
var sortedTimeState : Bool = false
var sortedPrioState : Bool = false
@IBOutlet weak var tableReminders: UITableView!
@IBOutlet weak var timeSortBtn: UIButton!
@IBOutlet weak var sortBtn: UIButton!
@IBOutlet weak var prioritySortBtn: UIButton!
@IBAction func BtnSort(_ sender: Any) {
sortList(sender: sortBtn) // sorts by a-z through the sort function
}
@IBAction func btnSortTime(_ sender: Any) {
sortList(sender: timeSortBtn)
}
@IBAction func btnSortPriority(_ sender: Any) {
sortList(sender: prioritySortBtn)
}
func sortList(sender: UIButton) { // should probably be called sort and not filter
if sender.tag == 1 && sortedAZState == false {
reminders.sort() { $0.reminderName < $1.reminderName } // sort the reminder by name
tableReminders.reloadData(); // notify the table view the data has changed
print("sender.tag 1")
sortedAZState = true
}
else if sender.tag == 1 && sortedAZState == true {
reminders.sort() { $0.reminderName > $1.reminderName } // sort the reminder by name
tableReminders.reloadData(); // notify the table view the data has changed
print("sender.tag 1")
sortedAZState = false
}
else if sender.tag == 2 && sortedTimeState == false {
reminders.sort { $0.reminderSavedTime.compare($1.reminderSavedTime) == .orderedAscending }
tableReminders.reloadData();
print("sender.tag 2")
sortedTimeState = true
}
else if sender.tag == 2 && sortedTimeState == true {
reminders.sort { $0.reminderSavedTime.compare($1.reminderSavedTime) == .orderedDescending }
tableReminders.reloadData();
print("sender.tag 2")
sortedTimeState = false
}
else if sender.tag == 3 && sortedPrioState == false {
reminders.sort() { $0.reminderPriority.count < $1.reminderPriority.count } // sort the reminder by priority
tableReminders.reloadData(); // notify the table view the data has changed
print("sender.tag 3")
sortedPrioState = true
}
else if sender.tag == 3 && sortedPrioState == true {
reminders.sort() { $0.reminderPriority.count > $1.reminderPriority.count } // sort the reminder by priority
tableReminders.reloadData(); // notify the table view the data has changed
print("sender.tag 3")
sortedPrioState = false
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Create an object of the dynamic cell "plainCell"
let cell = tableView.dequeueReusableCell(withIdentifier: "ReminderTableViewCell", for: indexPath) as! ReminderTableViewCell
// Depending on the section, fill the textLabel with the relevant text
// Reminder Section
cell.reminderLabel.text = filteredReminder[indexPath.row].reminderName
if filteredReminder[indexPath.row].reminderPriority == "!" {
let yourImage: UIImage = UIImage(named: "lowpriority")!
cell.priorityImage.image = yourImage
}
else if filteredReminder[indexPath.row].reminderPriority == "!!" {
let yourImage: UIImage = UIImage(named: "mediumpriority")!
cell.priorityImage.image = yourImage
}
else if filteredReminder[indexPath.row].reminderPriority == "!!!" {
let yourImage: UIImage = UIImage(named: "highpriority")!
cell.priorityImage.image = yourImage
}
/* I DON'T KNOW WHAT THIS COMPLETION FOR, HOPE IT IS WORKING A/C TO YOUR NEED. */
// cell.completeButtonAction = { [unowned self] in
// let reminderCall = reminders[indexPath.row].reminderName
// let alert = UIAlertController(title: "Complete!", message: "You have completed \(reminderCall).", preferredStyle: .alert)
// let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
// alert.addAction(okAction)
//
// reminders.remove(at: indexPath.row)
// self.tableReminders.deleteRows(at: [indexPath], with: .fade)
// convertAndSaveInDDPath(array: reminders)
//
// print("reminder deleted")
//
// self.present(alert, animated: true, completion: nil)
// }
//
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
print(reminders[indexPath.row].reminderName)
let selectedReminder = reminders[indexPath.row].reminderName
let destinationVC = EditReminderViewController()
destinationVC.reminderPassed = selectedReminder
performSegue(withIdentifier: "editSegue", sender: indexPath)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
filteredReminder.remove(at: indexPath.row)
tableReminders.deleteRows(at: [indexPath], with: .fade)
print(filteredReminder)
convertAndSaveInDDPath(array: filteredReminder) // UNCOMMENT THIS
}
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
// var decapValue = searchBar.text?.lowercased()
// print(decapValue!)
// print(LinearSearch(searchText: decapValue!, array: reminders))
if searchBar.text != "" {
self.filteredReminder = originalReminder.filter({ reminder -> Bool in
return reminder.reminderName.lowercased().contains(searchText.lowercased())
})
}
else {
self.filteredReminder = self.originalReminder
}
tableReminders.reloadData()
// print(filterData)
}
/*
func LinearSearch(searchText: String, array: [Reminder]) -> Bool { // search function to return a true or a false bool (contains two parameneters, search value and array
for i in reminders { // cycles through each element in the array
if i.reminderName.lowercased().contains(searchText) { // if element = search (return true)
filterData.append(i)
print(filterData)
return true
}
}
return false // returns false if no element comes back to equal the searchValue
}
*/
@IBAction func btnAdd(_ sender: Any) {
performSegue(withIdentifier: "addSegue", sender: (Any).self)
}
override func viewDidLoad() {
super.viewDidLoad() // example cell
// reminders.append(Reminder(reminderName: "HOMEWORK", reminderPriority: "LOW", reminderDate: "4324", reminderStatus: "INCOMPLETE"))
tableReminders.dataSource = self
tableReminders.delegate = self
searchBar.delegate = self
tableReminders.reloadData()
// print file path of array saved
// print(getFilePath(fileName: "remindersArray"))
let reminderRetrievedArray = getArray()
reminders = reminderRetrievedArray!
originalReminder = reminders
gfilteredReminder = reminders
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
我不知道你要的是哪个代码,所以这里都有。但是是的,你是对的,它一次删除一个,但它正在保存一个空数组以供下次打开时加载。
【问题讨论】:
-
在
if filtered == true条件下,此行是错误的 ->tableReminders.deleteRows(at: [indexPath], with: .fade)。删除它并尝试。 -
@dahiya_boy 当我这样做时,它不会崩溃,是的,它会从数组中删除它,但它会保留在 tableview 中,直到我再次触摸搜索栏,如果这有任何意义,我想要桌子查看不显示已删除的值,甚至在我触摸搜索栏之前
-
请记住,当您执行
deleteRow或insertRow时,您还需要对数据源执行相同的操作。在您的filtered == true中,您正在创建更改对象引用的新数据源。从开发人员的角度来看,您会看到值,但机器检查地址已更改。在filtered == false中你做得很完美,这就是为什么它可以工作而true不是。 -
@dahiya_boy 我将如何在过滤部分执行此操作?
-
这取决于您的功能。它如何为用户工作?什么是用户交互?
标签: ios swift tableview searchbar