how to do protocol to pass data?

Hello,


I'm a beginner with Swift and I'm struggling to understand the way the variables are send between class one and class two using protocol.


I want to create a data model for monitoring the heart rate. This data is displayed on the screen so that the user can see them. In parallel, it needs to check this data, i.e. print to the console what the label shows. I can not understand why the delegate property does not get a value (it has always nil) and why it does not print a phrase about what the user sees?


Technologies: XCODE Version 9.2, swift 4.


How can I solve this?


Thanks in advance.


CODE:


import UIKit

protocol HeartRateReceiverDelegate {
    func heartRateUpdated(to bpm: Int)
}

class HeartRateReceiver {
    var delegate: HeartRateReceiverDelegate?
    var currentHR: Int? {
        didSet {
            if let currentHR = currentHR {
                print("The most recent heart rate reading is \(currentHR).")
                delegate?.heartRateUpdated(to: currentHR)
                print("CurrentHR is \(currentHR)") // Check value
                print("Delegate is \(delegate)") // Check value
            } else {
                print("Looks like we can't pick up a heart rate.")
            }
        }
    }
    func startHeartRateMonitoringExample() {
        for _ in 1...10 {
            let randomHR = 60 + Int(arc4random_uniform(UInt32(15)))
            currentHR = randomHR
            Thread.sleep(forTimeInterval: 2)  
        }
    }
}
class HeartRateViewController: UIViewController, HeartRateReceiverDelegate {
    var heartRateLabel: UILabel = UILabel()
    func heartRateUpdated(to bpm: Int) {
        heartRateLabel.text = String(bpm)
        print("The user has been shown a heart rate of heartRateLabel.text")
    }
}

let heartRateReceiver = HeartRateReceiver()
heartRateReceiver.startHeartRateMonitoringExample()

var heartRateViewController = HeartRateViewController()

heartRateReceiver.delegate = heartRateViewController

Accepted Reply

First of all, if you want to learn iOS programming, you should remember this is not a usual way to instantiate a view controller.

var heartRateViewController = HeartRateViewController()

This may work as expected only in very limited condition.


But, in your case, you use this instance only as a delegate, so it should work if you properly set it.


Why your delegate is always nil?


Because you call `startHeartRateMonitoringExample()` before you set `delegate`.


Try changing the order of the 4 lines.

let heartRateReceiver = HeartRateReceiver()
var heartRateViewController = HeartRateViewController()
heartRateReceiver.delegate = heartRateViewController 
heartRateReceiver.startHeartRateMonitoringExample()

Your `startHeartRateMonitoringExample()` finishes after its 10 iterations of setting `currentHR`.

And in your code, `heartRateReceiver.delegate = heartRateViewController` is executed after `startHeartRateMonitoringExample()` is finished.


And you should better remember one more thing. You should never call `sleep` in the main thread in an app.

Use `Thread.sleep(forTimeInterval: 2)` only in the Playground and never use it in actual apps.


You usually use `Timer` when you want to invoke repeated tasks with interval.

Replies

The same question - what happens next when the propery currentHR is not nil?

Each statement in the true-block is executed under the established environment.

At the end of the true-block, the new local variable inner `currentHR` is discarded, so the once shadowed outer `currentHR` is visible again.

this is a part of the code:


https://drive.google.com/open?id=1u3BcBQs3HpAyG8CKdAGtLVp-oLC4wJaj



Why is new local variable inner `currentHR' discarded?


We say that the external variable 'currentHR' is not equal to nil. In this case, it is assigned to the inner variable, and that in turn is passed to the 'delegate' variable.

Your image does not include the end of true-block, so I cannot understnd what you are asking.


We say that the external variable 'currentHR' is not equal to nil. In this case, it is assigned to the inner variable, and that in turn is passed to the 'delegate' variable.


Seems true, what's the matter with that?