Swift设置委托给自己提供EXC_BAD_ACCESS [英] Swift set delegate to self gives EXC_BAD_ACCESS

查看:299
本文介绍了Swift设置委托给自己提供EXC_BAD_ACCESS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过移植现有应用程序来学习Swift。我被困在设置一个代表,无法解决问题。



我有一个扩展UITableViewCell的类

  import UIKit 

协议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)
}

}

然后在ViewController中定义为

  class SettingsViewController:UIViewController ,UITableViewDelegate,UITableViewDataSource,SwitchCellDelegate {

并在方法

  func tableView(tableView:UITableView !, cellForRowAtIndexPath indexPath:NSIndexPath!) - > UITableViewCell! {

我们有

  case 2:
storeCredentialsCell = tableView.dequeueReusableCellWithIdentifier(StoreCredentialsCell)as? SwitchCell
if(storeCredentialsCell!= nil){
...
NSLog(将代理设置为%@ for%@,self.description,storeCredentialsCell.description)
storeCredentialsCell !.delegate = self
...
}

日志输出是正如预期的那样,当它与代理的实际设置匹配时,应用程序会崩溃与


EXC_BAD_ACCESS(code = 1,address = 0xfffffffffffffff8) p>

我还应该注意,如果在委托?.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)
}

覆盖func viewDidLoad(){
super .viewDidLoad()
}

覆盖func didReceiveMemoryWarning(){
super.didReceiveMemoryWarning()
}

覆盖func numberOfSectionsInTableView(tableView :UITableView?) - > int {
return 1
}

覆盖func tableView(tableView:UITableView?,numberOfRowsInSection部分:Int) - > int {
return 1
}

覆盖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
}

返回单元格
}

func eventFired(发件人:TestCell){
NSLog(Hooray!)
}

TestCell.swift

 导入UIKit 

协议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)
}
}

然后我创建了一个具有TestTableViewController类的表视图控制器场景。表视图是动态的,具有TestCell类型的单个单元格。该单元格包含一个标签和一个与TestCell类的IBOutlets绑定的开关。 switchChanged函数绑定到交换机上的值更改事件。



相同的EXC_BAD_ACCESS错误被抛出。

解决方案

目前,如果委托应该是Objective-C类的对象,那么您必须使用 @objc 显式标记协议(像UITableViewController):

  @objc协议SwiftProtocol 

这将实现与Objective-C


的互操作

I'm going through and learning Swift by porting an existing application. I'm stuck on setting a delegate and cannot work out what the issue is.

I have a class which extends 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)
    }

}

Then in the ViewController is defined as

class SettingsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SwitchCellDelegate {

and within the method

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {

we have

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

the log output is as expected but when it hits the actual setting of the delegate the app crashes with

EXC_BAD_ACCESS(code=1, address=0xfffffffffffffff8)

I should also note that if I don't set the delegate value when delegate?.switchChanged(self, state: swtSelector.on) fires it also causes an EXC_BAD_ACCESS error but according to the doco for delegates this should fail gracefully if delegate is not set to anything.

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

I've simplified down to a basic project to replicate the issue.

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!")
    }

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

I then created a single Table View Controller Scene with Class of TestTableViewController. The table view is dynamic with a single cell of type TestCell. That cell contains one label and one switch which are bound to the IBOutlets from the TestCell class. The switchChanged function is bound to the value changed event on the switch.

Same EXC_BAD_ACCESS error is thrown.

解决方案

Currently you have to explicitly mark your protocols with @objc if the delegate should be an Object of a Objective-C class (Like the UITableViewController):

@objc protocol SwiftProtocol

This will enable interoperating with Objective-C

这篇关于Swift设置委托给自己提供EXC_BAD_ACCESS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆