从另一个视图调用表视图函数

Posted

技术标签:

【中文标题】从另一个视图调用表视图函数【英文标题】:Call a UITableViewFunction from another view 【发布时间】:2018-03-20 14:27:06 【问题描述】:

我有一个由UITableView 调用的function,它根据它包含的内容更新钱包值(因此由tableView 调用)。这是WalletViewController 的一部分,用户可以在其中更新他的钱包所包含的内容。

我希望能够从MainViewController 调用此函数,其中还显示了钱包值,因此当用户刷新数据时它是最新的,目前仅发生钱包值更新功能当你加载 WalletViewControllerreloadData() 时被调用。

如何才能刷新MainViewController 中的值?

数值更新功能的WalletViewController代码:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! WalletTableViewCell

    cell.delegate = self
    cell.amountTextField.delegate = self

    updateCellValueLabel(cell, atRow: indexPath.row)

    return cell


func updateCellValueLabel(_ walletTableViewCell: WalletTableViewCell, atRow row: Int) 

    //... calculations for each wallet's object are happening here ...

    CoreDataHandler.editObject(editObject: selectedAmount, amount: amount, amountValue: currentAmountValue) 
    // <--- calculations result for each object is saved to CoreData

    updateWalletValue()
    updateWalletLabel()


func updateWalletValue() 

    var items : [CryptosMO] = []

    if CoreDataHandler.fetchObject() != nil 
        items = CoreDataHandler.fetchObject()! 
    // <--- Calculations result are fetched from CoreData
    

    total = items.reduce(0.0,  $0 + Double($1.amountValue)!  )
    // <--- Objects values are added together to get the wallet's grand total

    WalletTableViewController.staticTotal = total


func updateWalletLabel() 

    walletValueLabel.text = formatter.string(from: NSNumber(value: total))


MainViewController钱包更新功能至今:

func updateWalletLabel() 

    WalletTableViewController.init().updateWalletValue()

    walletValue.text = formatter.string(from: NSNumber(value: WalletTableViewController.staticTotal))


我想我应该从核心数据中获取钱包对象的数量并从MainViewController 重新计算以获取最新值?或者有没有更简单的解决方案来调用整个tableView 函数?

【问题讨论】:

在 MainViewController 中使用 post 通知和 addObserver。 请注意WalletTableViewController() 创建了控制器的一个新实例,它不是故事板中的实例。您需要对控制器的实际引用。 @MRizwan33 会是什么样子? @PhillipMills 对不起,您是什么意思?我知道这不是你的意思,但我的核心数据功能不在视图控制器中。 如果WalletTableViewController 来自MainViewController,请保留前者的引用。 【参考方案1】:

有几种方法可以做到这一点。如果您想走“发布通知”路线,@MRizwan33 的答案将起作用。

我通常会做的另一种选择是从您的MainViewController 获取对您的WalletViewController 的引用,然后直接在WalletViewControllerInstance 上拨打电话:

class MainViewController: UIViewController 

    // Local variable to cache instance of WalletViewController
    var walletVC: WalletViewController?

    func functionWhereWalletViewControllerIsInstantiated() 
        // Save the reference to the WalletViewController instance
        walletVC = self.storyboard?.instantiateViewController(
                withIdentifier: "WalletViewControllerIdentifier") as!
                        WalletViewController
    

    func someFuncWhereYouWantToUpdateWalletViewController() 
        // Call the function on your cached WalletViewController
        // instance that performs the refresh
        walletVC.doTheUpdate()
     

如果你在推送的地方实例化walletVC,你可以这样做:

func functionWhereWalletVcIsPushed() 
    if (walletVC == null) 
        walletVC = self.storyboard?.instantiateViewController(
                withIdentifier: "WalletViewControllerIdentifier") as!
                        WalletViewController
    
    // Push the view controller

你也可以让属性变得懒惰:

lazy var walletVC: WalletViewController = 
    return self.storyboard?.instantiateViewController(
                    withIdentifier: "WalletViewControllerIdentifier") as!
                            WalletViewController

(我不是 Swift 专家,所以您需要仔细检查语法)

【讨论】:

非常感谢!我能理解你在这里做什么,这很棒!然后doTheUpdate() 将是WalletViewControllerupdateWalletValue() 的更新版本,其中的reloadData() 表是否太正确? 对不起,我在推送视图时打电话给instantiateViewController(withIdentifier:)。我现在应该什么时候打电话?谢谢! 如果你愿意,你仍然可以在那里做。最简单的方法是在推送之前检查if (walletVC == null) /* Instantiate */ 。另一种选择是将walletVC 设为惰性属性,以便在首次访问时对其进行实例化。 好吧,一切都设置好了,不幸的是,用walletVC.doTheUpdate() 调用tableView.reloadData() 来获取最新数据并更新钱包值会导致应用程序在Found nil 崩溃,这是有道理的,因为tableView 不是显示。我能做什么? 您似乎需要重新设计WalletViewController 中的更新功能的工作方式。显然你不能在 nil TableView 上调用reloadData()。您要在“MainViewController”中显示的究竟是什么?如果它是在 WalletViewController 中计算并保存在其他位置(CoreData?)的某个值,您应该考虑将该逻辑移动到另一个类并将其从 MainViewController 传递到 WalletViewController 作为依赖项。【参考方案2】:

在您想要调用更新另一个视图的位置使用此行。

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)

添加将发生更新的这些行:

NotificationCenter.default.addObserver(self, selector: #selector("Your Method Name Which you want to call on change like (reloadTableView)"), name: Notification.Name("NotificationIdentifier"), object: nil)

【讨论】:

非常感谢!你能指点我把它们放在我的代码中的什么地方吗?我猜addObserver 会出现在WalletViewController 的某个地方,而post 会出现在MainViewControllerupdateWalletLabel() 中? addObsever 将在 MainViewController 中,并在选择器“updateWalletLabel()”中写入方法,并且 post 将在钱包值更改的 walletViewController 中。

以上是关于从另一个视图调用表视图函数的主要内容,如果未能解决你的问题,请参考以下文章

从另一个视图重新加载表视图

从另一个表创建视图

无法从另一个视图控制器获取表视图数据

如何通过iOS Objective C中的appDelegate从另一个视图控制器重新加载表视图

iPhone - 从另一个视图控制器调用函数

当从 iOS 中的另一个故事板场景调用 viewController 时,表视图变得空白(加载或重建)