将数据传回之前的视图控制器(类型错误时不能使用实例成员)。

问题描述 投票:-1回答:1

我有2个值,跟踪我的用户可以在应用程序中购买的福利类型的当前值。我想在 purchaseViewController 中更新它们,一旦 purchaseViewController 被解散,就在前一个视图控制器中使用它们。我已经尝试用协议委托人和回调来实现这个目标。然而,我得到的错误基本上是一样的,都说 "实例成员'delegatecallback'不能用于'purchaseViewController'类型"。这是我第一次尝试传回数据,我主要是跟着教程走,可能在路上错过了一个步骤,但我觉得很奇怪,两个方法都得到相同类型的错误。

父视图控制器上的代码。

func sendBack(staticIncreases: Int, percentIncreases: Int) { //Protocol function
    self.avalibleIncreases = staticIncreases
    self.currentPercentIncreases = percentIncreases
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier ==  "improveFromOpen"{
        let next = segue.destination as! purchasesViewController
        next.currentPercentIncreases = currentPercentIncreases
        next.username = username
        next.avalibleIncreases = avalibleIncreases
        purchasesViewController.delegate = self //Error "Instance member 'delegate' cannot be used on type 'purchasesViewController'"
        purchasesViewController.callback = { result in //Error "Instance member 'delegate' cannot be used on type 'purchasesViewController'"
            self.avalibleIncreases = result[0]
            self.currentPercentIncreases = result[1]
        }
    }

父视图控制器上的代码: 购买视图控制器上的代码:

protocol updateBoosts {
    func sendBack(staticIncreases: Int, percentIncreases: Int)
}

class purchasesViewController: UIViewController {

    var delegate: updateBoosts? = nil
    var callback : (([Int])->())?

    var username: String!
    var currentPercentIncreases: Int!
    var avalibleIncreases: Int!

func sendBackVals(){
    if self.delegate != nil {
        self.delegate?.sendBack(staticIncreases: avalibleIncreases, percentIncreases: currentPercentIncreases)
    }

    let out = [avalibleIncreases!, currentPercentIncreases] as [Int]
    callback?(out)
}

override func viewWillDisappear(_ animated: Bool) {
    sendBackVals()
}

知道我的错误在哪里吗?

ios swift uiviewcontroller callback delegates
1个回答
0
投票

你的代码有几个设计问题。

你应该使用以下两种方法 delegateclosure 一次,因为两者的用途相同。否则,同样的事情会被执行两次。

如果你使用委托人,你将不得不改变你的协议,如下所述。另外,你还必须确认协议。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier ==  "improveFromOpen"{
        let next = segue.destination as! purchasesViewController
        next.currentPercentIncreases = currentPercentIncreases
        next.username = username
        next.avalibleIncreases = avalibleIncreases
        next.delegate = self 
    }
}

确认协议

假设当前的视图控制器,你想获得回调的地方是 HomeViewController

// Confirming the protocol
extension HomeViewController: UpdateBoostsDelegate {
   func sendBack(staticIncreases: Int, percentIncreases: Int) {
    // write code here for handling the callback
   }
}

如果你想使用closure,那就把delegate去掉。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier ==  "improveFromOpen"{
        let next = segue.destination as! purchasesViewController
        next.currentPercentIncreases = currentPercentIncreases
        next.username = username
        next.avalibleIncreases = avalibleIncreases
        next.callback = { result in
                self.avalibleIncreases = result[0]
                self.currentPercentIncreases = result[1]
       }
    }
// Would be good if you add the semantic to protocol name
protocol UpdateBoostsDelegate: class {
    func sendBack(staticIncreases: Int, percentIncreases: Int)
}

还有一些修正,在 PurchaseViewController

class purchasesViewController: UIViewController {
// Make it weak so that no retain cycle is formed
   weak var delegate: UpdateBoostsDelegate?
// rest code will follow ....

建议

  1. 对于Classes、struct、enum、protocol,每个词的第一个字符都应该是大写的。
  2. 协议应该有语义,即如果创建协议是为了通知事件,那么就加上 代表 postfix,或者如果是为了满足数据需求而创建的,则添加 数据源 后缀在协议名中。

更多关于关闭

授权设计模式

© www.soinside.com 2019 - 2024. All rights reserved.