Swift: Delegation protocol not setting UILabel pro

2019-09-10 00:14发布

问题:

I have the following Protocol:

protocol SoundEventDelegate{
  func eventStarted(text:String)
}

which I call in this class:

class SoundEvent {
  var text:String
  var duration:Double
  init(text: String, duration: Double){
    self.text = text
    self.duration = duration
}

var delegate : SoundEventDelegate?

func startEvent(){
    delegate?.eventStarted(self.text)

}

  func getDuration() -> Double{
    return self.duration //TODO is this common practice?
  }

} 

Which I have my ViewController conform to:

class ViewController: UIViewController, SoundEventDelegate {
  //MARK:Properties
  @IBOutlet weak var beginButton: UIButton!
  @IBOutlet weak var kleinGrossLabel: UILabel!

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

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

  //DELEGATE method
  func eventStarted(text:String){
    kleinGrossLabel.text = text
  }

  //MARK: actions
  @IBAction func startImprovisation(sender: UIButton) {
    var s1:Sentence = Sentence(type: "S3")
    var s2:Sentence = Sentence(type: "S1")
    var newModel = SentenceMarkov(Ult: s1, Penult: s2)
    s1.start()
    beginButton.hidden = true
  } 
}

But when I run the app kleinGrossLabel.text does not change. Am I referring to the label in the wrong way? Or is it the way that I do delegation that is incorrect?

Here are links to the complete Class definitions of Sentence and SentenceMarkov

https://gist.github.com/anonymous/9757d0ff00a4df7a29cb - Sentence

https://gist.github.com/anonymous/91d5d6a59b0c69cba915 - SentenceMarkov

回答1:

First off it's not common practice to have a setter in swift. if you want to have a readonly property you can use private(set) var propertyName in other cases simply access the property like mentioned in the comment

Also i don't see a reason why you eventArray in sentence is of type [SoundEvent?] not [SoundEvent] as SoundEventdoes not seem to have a failable initialiser

Like mentioned before you need to not only implement the SoundEventDelegate protocol but also set the delegate

the problem is that you can't really access the SoundEventDelegate from the viewcontroller because you instantiate the SoundEvents inside Sentence

var soundEventDelegate: SoundEventDelegate?

the easiest way to do this would be adding a soundEventDelegate property for sentence and setting it like this:

let s1:Sentence = Sentence(type: "S3")
let s2:Sentence = Sentence(type: "S1")
s1.soundEventDelegate = self
s2.soundEventDelegate = self

and inside sound you would need the set the delegate for every event to the soundEventDelegate of Sentence

you could do it like this:

var soundEventDelegate: SoundEventDelegate? = nil {
    didSet {
        eventArray.forEach({$0.delegate = soundEventDelegate})
    }
}

or write another initialiser that takes the delegate

hope this helps

p.s: you shouldn't inherit form NSObject in swift excepts it's really necessary



回答2:

You never set the delegate property. It's nil. It will never be called.