【问题标题】:Passing data back to previous view controller (Instance member cannot be used on type error)将数据传回前一个视图控制器(实例成员不能用于类型错误)
【发布时间】:2020-09-07 20:24:34
【问题描述】:

我有 2 个值来跟踪我的用户可以在应用内购买的福利类型的当前值。我想在purchaseViewController 中更新它们,并在purchaseViewController 被解除后在前一个视图控制器中使用它们。我尝试使用协议/委托和回调来做到这一点。但是,我得到了基本相同的错误,两者都说“实例成员'delegate/callback'不能用于类型'purchasesViewController'”。这是我第一次尝试将数据传回,我主要只是在学习教程,可能错过了一步,但我认为这两种方法都会出现相同类型的错误,这很奇怪。

父视图控制器上的代码:

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]
        }
    }

purchaseViewController 上的代码:

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】:

您的代码存在一些设计问题。

您应该一次使用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
   }
}

如果您想使用闭包,请移除委托。

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. 对于类、结构、枚举、协议,每个单词的第一个字符应始终为大写。
  2. 协议应该具有语义,即如果创建它是为了通知事件然后添加Delegate后缀,或者如果它是为了满足数据需求而创建的,则添加Datasource 协议名称中的后缀。

More about closure

Delegation design pattern

【讨论】:

  • 我尝试实施您建议的更改,当我从准备 segue 中删除代表时,我收到与之前有关关闭的相同错误。我还为委托/协议流程实现了你们所有的建议,然后摆脱了闭包,但再次出现相同的“实例成员 'delegate' 不能用于类型 'purchasesViewController';你的意思是使用这种类型的值吗? ?”与以前在同一行出现错误。此外,不确定它是否应该,但是当我输入 purchasesViewController.delegate 时,它绝不会像处理大多数其他事情一样自动建议委托
  • @hudsonhooper 让我们在这里讨论chat.stackoverflow.com/rooms/214353/ios-basic-discussion
  • 再次检查代码,您将不得不使用next,它是purchasesViewController 的一个实例,您应该设置委托或闭包,例如next.delegatenext.callback = { result in self.avalibleIncreases = result[0] self.currentPercentIncreases = result[1] }
  • 不客气 :) 那么你应该接受@hudsonhooper 的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-15
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 2015-11-27
相关资源
最近更新 更多