繁体   English   中英

如何 select 使用 Realm 从 Swift 中的数组中删除当前项

[英]How to select the current item to delete it from an array in Swift using Realm

因此,我尝试通过互联网和 StackOverflow 寻找答案,但我不确定要寻找什么,所以答案可能已经共享。 所以我很抱歉,因为我是菜鸟。 但是,我仍然需要帮助。 (请,)我有一个我正在使用的应用程序,其中包含一个充满零件的表格视图,其中包含一个详细信息零件页面,其中提供了零件的详细信息(零件名称、零件编号、描述等)

我在页面末尾有一个删除按钮,当您单击它时,它会询问您是否要删除,您确定吗? 如果用户说是,则该部分将被删除,但删除仅从 tableview 中删除了最后一个项目,即最近添加的项目。 我知道,是因为我调用了以下 function:

    func deletePart() {
        if let partToDelete = getPartsArray().last {
            try! realm.write {
                realm.delete(partToDelete)
            }
        }

用'getPartsArray()。 最后'

我正在尝试查看如何删除表视图中的当前选定部分。 现在,我可以选择顶部的第二部分,如果我单击该部分的删除按钮,它将始终从 tableview 中删除最后一部分。

这是 getPartsArray function 的代码:

    func getPartsArray() -> [PartInfo] {
        return getAllParts().map { $0 }
    }

我(笨拙地)已经尝试过:使用'getPartsArray()。 当前' 显然这不是一回事,哈哈。

我也在想,既然我使用的是 REALM / Mongo DB,我可以通过它的 ID 找到零件吗? 然后删除它? 但我也不确定如何找到当前 select 部件的 id。

任何帮助将非常感激。 谢谢!

编辑:这是我的 TableView 代码:

//
//  ViewAllPartsViewController.swift
//  PartKart
//
//  Created by Kiarra Julien on 10/20/21.
//

import Foundation
import UIKit

class ViewAllPartsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, CurrencyFormatter  {
    
    private var brain = PartKartBrain()
    
    private var parts = [PartInfo]()
    
    @IBOutlet var tableView: UITableView!
    
    @IBAction func returnHome() {
        dismiss(animated: true, completion: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let nib = UINib(nibName: "DemoTableViewCell", bundle: nil)
        tableView.register(nib, forCellReuseIdentifier: "DemoTableViewCell")
        tableView.delegate = self
        tableView.dataSource = self
        
        parts = brain.getPartsArray()
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        parts.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "DemoTableViewCell", for: indexPath) as! DemoTableViewCell
        
        cell.partNameLabel.text = parts[indexPath.row].partName
        
        // Convert string value to double
        cell.partCostLabel.text = formatCurrency(value: parts[indexPath.row].partCost)
        //        String(format: "$%.2f", parts[indexPath.row].partCost)
        cell.purchaseDateLabel.text = parts[indexPath.row].purchaseDate
        // cell.textLabel?.text = parts[indexPath.row].partName
        // cell.textLabel?.numberOfLines = 0countTotalParts()
        // cell.textLabel?.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        performSegue(withIdentifier: "showPartDetails", sender: parts[indexPath.row])
    }
    
    // MARK: - Navigation
    
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
        if let viewcontroller = segue.destination as? PartDetailsViewController {
            viewcontroller.part = sender as? PartInfo
        }
    }
    
    
}

这就是我所说的删除部分:

class PartDetailsViewController: UIViewController, CurrencyFormatter {
    
    //Store Information Labels
    @IBOutlet weak var storeNameLabel: UILabel!
    @IBOutlet weak var storeNumLabel: UILabel!
    @IBOutlet weak var storeAddrLabel: UILabel!
    
    //Part Information Labels
    @IBOutlet weak var partNameLabel: UILabel!
    @IBOutlet weak var partNumLabel: UILabel!
    @IBOutlet weak var partDescLabel: UILabel!
    @IBOutlet weak var partCostLabel: UILabel!
    @IBOutlet weak var partQtyLabel: UILabel!
    @IBOutlet weak var purchaseDateLabel: UILabel!
    @IBOutlet weak var hasWarrantySwitch: UISwitch!
    @IBOutlet weak var warrantyLengthLabel: UILabel!
    
    //Mechanic Information Labels
    @IBOutlet weak var mechanicNameLabel: UILabel!
    @IBOutlet weak var mechanicNumLabel: UILabel!
    @IBOutlet weak var mechanicAddrLabel: UILabel!
    @IBOutlet weak var laborCostLabel: UILabel!
    @IBOutlet weak var serviceDateLabel: UILabel!
    
    var part: PartInfo?
    let brain = PartKartBrain()
    
    @IBAction func deletePartBtn(_ sender: UIButton) {
        
        // Declare Alert message
                let dialogMessage = UIAlertController(title: "Confirm", message: "Are you sure you want to delete this part?", preferredStyle: .alert)
                
                // Create OK button with action handler
                let ok = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
                     print("Ok button tapped")
                    // I CALL DELETE PART RIGHT HEREEE!
                    self.brain.deletePart()
                    
                    // delay and then dismiss the page
                    let delayInSeconds = 0.5
                    DispatchQueue.main.asyncAfter(deadline: .now() + delayInSeconds) { [unowned self] in
                        dismiss(animated: true, completion: nil)
                    }
                })
                
                // Create Cancel button with action handlder
                let cancel = UIAlertAction(title: "Cancel", style: .cancel) { (action) -> Void in
                    print("Cancel button tapped")
                }
                
                //Add OK and Cancel button to dialog message
                dialogMessage.addAction(ok)
                dialogMessage.addAction(cancel)
                
                // Present dialog message to user
                self.present(dialogMessage, animated: true, completion: nil)
            }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
 
        
        title = part?.partName
        
        //Set the Store Info Labels Equal to actual data
        storeNameLabel.text = part?.partName
        storeNumLabel.text = part?.storeNumber
        storeAddrLabel.text = part?.storeAddress // < ---- The address is cut off the screen!
        
        //Set the Part Info Labels Equal to actual data
        partNameLabel.text = part?.partName
        partNumLabel.text = part?.partNumber
        partDescLabel.text = part?.partDescription
        
        if let partCost = part?.partCost {
            partCostLabel.text = formatCurrency(value: partCost)
        }
        
        if let partQty = part?.partQuantity {
            partQtyLabel.text = String(partQty)
        }
        
        purchaseDateLabel.text = part?.purchaseDate
        
        //If there's no warranty, display 'N/A' instead
        if part?.hasWarranty == true {
                hasWarrantySwitch.isOn = true
                warrantyLengthLabel.text = part?.warrantyLength
              } else {
                hasWarrantySwitch.isOn = false
                warrantyLengthLabel.text = "N/A"
              }
        
        //Set the Mechanic Info Labels Equal to actual data
        mechanicNameLabel.text = part?.mechanicName
        mechanicNumLabel.text = part?.mechanicNumber
        mechanicAddrLabel.text = part?.mechanicAddress
        //laborCostLabel.text = part?.laborCost
  
        if let laborCost = part?.laborCost {
            laborCostLabel.text = formatCurrency(value: laborCost)
        }
        
        serviceDateLabel.text = part?.serviceDate
        
        
        
    }
}

让我把 state 问题回给你

“如何从我的表格视图中删除选定的行”?

如果这是问题,让我们提供一个简单的答案

首先,在使用 Realm 时不要这样做

return getAllParts().map { $0 }

Realm 对象被延迟加载到结果 object 中。 一旦您针对高级别的 function (例如 map、reduce 等)运行它们(将它们存储在数组中),它们都会被加载到 memory 中,如果您拥有一个庞大的数据集,那么您将淹没设备。 此外,如果您有排序等,您的对象将与底层 Realm 数据不同步。

您最好的选择是利用 Realm 结果作为您的 tableView 数据源 - 它的行为很像数组。

所以这是一个viewController class,它有一个部分Results object作为tableView数据源

class InStockVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
    var partsNotificationToken: NotificationToken!
    var partsResults: Results<PartsClass>! //the tableView dataSource

假设用户点击或选择第 2 行,然后点击或单击“删除”

//pseudocode    
let selectedRow = tableView.selectedRow 
let part = partResults[selectedRow]
try! realm.write {
   realm.delete(part)
}

上面的代码确定选择了表中的哪一行,从结果中获取 object 部分,然后告诉 Realm 删除它。

一旦从 Realm 中删除 object,partsResults object 就会反映该更改,并且自动删除 ZA8CFDE6331BD59EB66AC96F891111。 您唯一需要做的就是在 UI 中反映这种变化。

有很多方法可以处理动画等,但为了简单起见,让我们重新加载 tableView,这样删除的行就不再显示了。

注意在上面的代码中,还有一个var partsNotificationToken: NotificationToken! ,该令牌是结果 object 的观察者 - 当基础数据中的某些内容发生更改时,结果 object 也会发生变化,并且通知令牌会触发观察者操作来处理该更改。 这是一个示例观察者

self.partsNotificationToken = self.partsResults.observe { changes in
    switch changes {
    case .initial:
        self.tableView.reloadData() //update the tableview after data is initially loaded

    case .update(_, _, _, _):
        self.tableView.reloadData() //update the tableView after changes

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM