2014-06-10 18 views
9

Sto passando e apprendo Swift effettuando il porting di un'applicazione esistente. Sono bloccato sull'impostazione di un delegato e non riesco a capire qual è il problema.Swift set delegate to self dà EXC_BAD_ACCESS

Ho una classe che estende 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) 
    } 

} 

Poi nella ViewController è definito come

class SettingsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SwitchCellDelegate { 

e nel metodo

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

abbiamo

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

l'output del registro è come previsto, ma quando colpisce l'impostazione attuale del delegato l'applicazione si blocca con

EXC_BAD_ACCESS (codice = 1, indirizzo = 0xfffffffffffffff8)

Vorrei anche notare che se non imposto il valore del delegato quando delegato? .switchChanged (self, state: swtSelector.on) lo spara causa anche un errore EXC_BAD_ACCESS ma secondo il doco per i delegati questo dovrebbe fallire con garbo se il delegato non è impostato su qualcosa.

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

Ho semplificato verso il basso per un progetto di base per replicare il problema.

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

Ho quindi creato un unico Table View Scene Controller con classe di TestTableViewController. La vista tabella è dinamica con una singola cella di tipo TestCell. Quella cella contiene un'etichetta e uno switch associati agli IBOutlet dalla classe TestCell. La funzione switchChanged è associata all'evento modificato del valore sullo switch.

Viene generato lo stesso errore EXC_BAD_ACCESS.

+0

Non riesco a riprodurre questo. Puoi pubblicare più codice? Hai provato a usare il debugger per fermarti sulla linea NSLog e vedere quali sono le variabili (come 'storeCredentialsCell',' self', ecc.)? – jtbandes

+0

Provare a inizializzare il delegato 'var delegate: SwitchCellDelegate?= nil' – Dash

+0

Questo è ciò che produce la linea NSLog: 2014-06-10 14: 31: 59.310 SmartDelivery [316: 60b] Impostazione delegato a <_TtC13CantaraClient22SettingsViewController: 0x13fd05ec0> per <_TtC13CantaraClient10SwitchCell: 0x13fd1f4f0; baseClass = UITableViewCell; frame = (0 0; 540 44); layer = > – Moth

risposta

21

Attualmente si deve contrassegnare esplicitamente i protocolli con @objc se il delegato dovrebbe essere oggetto di un Objective- Classe C (come UITableViewController):

@objc protocol SwiftProtocol 

Ciò consentirà l'interoperabilità con Objective-C

+4

man, swift è un casino! – Chet

+2

Potrebbe essere che Swift non è un disastro, ma una beta. Sembra che questo sia un bug che (speriamo) sarà risolto. Al momento (Xcode 6 beta 5), ​​i delegati forti funzionano bene, ma i delegati deboli continuano a non funzionare. – George

5

E ora per la soluzione ....

@objc protocol SwitchCellDelegate 

invece di

protocol SwitchCellDelegate