Swift将委托设置为self赋予EXC_BAD_ACCESS

Mot*_*oth 11 delegates exc-bad-access swift xcode6

我正在通过移植现有的应用程序来学习Swift.我一直坚持设置代表,无法解决问题所在.

我有一个扩展UITableViewCell的类

import UIKit

protocol SwitchCellDelegate{
    func switchChanged(switchCell: SwitchCell, state: Bool)
}

class SwitchCell: UITableViewCell {

    @IBOutlet var swtSelector: UISwitch
    @IBOutlet var lblTitle: UILabel

    var delegate: SwitchCellDelegate?

    init(style: UITableViewCellStyle, reuseIdentifier: String) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }

    @IBAction func switchChanged(){
        delegate?.switchChanged(self, state: swtSelector.on)
    }

}
Run Code Online (Sandbox Code Playgroud)

然后在ViewController中定义为

class SettingsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SwitchCellDelegate {
Run Code Online (Sandbox Code Playgroud)

并在方法内

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
Run Code Online (Sandbox Code Playgroud)

我们有

case 2:
    storeCredentialsCell = tableView.dequeueReusableCellWithIdentifier("StoreCredentialsCell") as? SwitchCell
    if(storeCredentialsCell != nil){
        ...
        NSLog("Setting delegate to %@ for %@", self.description, storeCredentialsCell.description)
        storeCredentialsCell!.delegate = self
        ...
    }
Run Code Online (Sandbox Code Playgroud)

日志输出是按预期的,但当它达到委托的实际设置时,应用程序崩溃

EXC_BAD_ACCESS(代码= 1,地址= 0xfffffffffffffff8)

我还应该注意,如果我没有在委托时设置委托值?.switchChanged(self,state:swtSelector.on)触发它也会导致EXC_BAD_ACCESS错误但是根据代表的doco,如果委托不是,则应该优雅地失败设置为任何东西.

===========================

我已经简化为一个基本项目来复制这个问题.

TestTableViewController.swift

import UIKit

class TestTableViewController: UITableViewController, TestCellDelegate {

    init(style: UITableViewStyle) {
        super.init(style: style)
    }

    init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
        let cell = tableView!.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? TestCell

        if(cell != nil){
            cell!.delegate = self
            cell!.lblTest.text = "Test Successful"
        }

        return cell
    }

    func eventFired(sender: TestCell) {
        NSLog("Hooray!")
    }
Run Code Online (Sandbox Code Playgroud)

TestCell.swift

import UIKit

protocol TestCellDelegate{
    func eventFired(sender: TestCell)
}

class TestCell: UITableViewCell {

    @IBOutlet var lblTest: UILabel
    @IBOutlet var swtTest: UISwitch

    var delegate: TestCellDelegate?

    init(style: UITableViewCellStyle, reuseIdentifier: String) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }

    @IBAction func switchChanged(sender: UISwitch){
        delegate?.eventFired(self)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我用Class of TestTableViewController创建了一个Table View Controller Scene.表视图是动态的,具有TestCell类型的单个单元格.该单元格包含一个标签和一个开关,它们与TestCell类的IBOutlets绑定.switchChanged函数绑定到交换机上的值更改事件.

抛出相同的EXC_BAD_ACCESS错误.

小智 21

目前,@objc如果委托应该是Objective-C类的Object(如UITableViewController),则必须明确标记协议:

@objc protocol SwiftProtocol
Run Code Online (Sandbox Code Playgroud)

这将实现与Objective-C的互操作

  • 可能是斯威夫特不是一团糟,而是一个测试版.似乎这是一个(我们希望)将被修复的错误.现在(Xcode 6 beta 5),强大的代表工作得很好,但弱代表仍然无法工作. (2认同)

Mot*_*oth 5

现在为解决方案....

@objc protocol SwitchCellDelegate
Run Code Online (Sandbox Code Playgroud)

代替

protocol SwitchCellDelegate
Run Code Online (Sandbox Code Playgroud)