Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a protocol either a reference or value type in Swift?

The reason I ask this question is because I'm reading a tutorial that uses delegation. Based on what I've read from other tutorials/articles online, to my knowledge this specific tutorial hasn't created a retain cycle. I also tested it by using Instruments (Memory leaks and zombies) to be sure there wasn't a memory leak.

I'm trying to figure out if a class were to simply conform to a protocol, does this create a reference?

I don't think it does but I want to be sure.

Here is the protocol and class that creates a delegate member:

import Foundation
import CoreBluetooth

protocol TransferServiceScannerDelegateProtocol: NSObjectProtocol {
    func didStartScan()
    func didStopScan()
    func didTransferData(data: NSData?)
}

class TransferServiceScanner: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
    var centralManager: CBCentralManager!
    var discoveredPeripheral: CBPeripheral?
    var data = NSMutableData()
    weak var delegate: TransferServiceScannerDelegateProtocol?

    init(delegate: TransferServiceScannerDelegateProtocol?) {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
        self.delegate = delegate
    }


    //start of cbCentralDelegate method
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
            print("Central is powered on...")
            break
        case .poweredOff:
            print("Central is powered off...")
            break
        default:
            print("Central manager changed state \(central.state)")
            break
        }
    }
    //end of cbCentralDelegate method

}

Here is a view controller that conforms to the protocol but also has a property which of the type class mentioned above. I'm not sure yet as to why this view controller conforms to the protocol but I don't think this should increase the reference count:

import UIKit

class CentralViewController: UIViewController, TransferServiceScannerDelegateProtocol {
    @IBOutlet var heartImage: UIImageView!
    @IBOutlet var scanButton: CustomButton!
    @IBOutlet var textView: UITextView!
    var transferServiceScanner: TransferServiceScanner!

    // MARK: TransferServiceScannerDelegateProtocol methods
    func didStartScan() {
        //
    }

    func didStopScan() {
        //
    }

    func didTransferData(data: NSData?) {
        //
    }
    //end of TransferServiceScannerDelegateProtocol methods


    override func viewDidLoad() {
        super.viewDidLoad()
        transferServiceScanner = TransferServiceScanner.init(delegate: self)
    }

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


    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */

}
like image 862
Laurence Wingo Avatar asked Nov 08 '22 02:11

Laurence Wingo


1 Answers

I don't think this should increase the reference count:

var transferServiceScanner: TransferServiceScanner increases the reference count to one, since all references are strong if they are not declared weak or sth else.

Storing the delegate variable as weak makes sure strong references do not go both ways and so ARC can deinit them.

I'm trying to figure out if a class were to simply conform to a protocol, does this create a reference?

A class is always a reference-type, whether you refer to it through a protocol or directly. So assigning a protocol with a reference-type(class) behind it does not copy the class-object, but you rather give out another reference to the object and increases the reference-count which ARC looks at.

With

protocol TransferServiceScannerDelegateProtocol: NSObjectProtocol {

you are making sure, that only a class can implement the protocol, that is why you can declare weak var delegate: TransferServiceScannerDelegateProtocol, because only classes can implement NSObjectProtocol with NSObject & co.

Without declaring a protocol class-only, either a struct or a class, both can implement the protocol. But only if you restrict the protocol to class-only can you use the protocol as if it were a class, using things like weak with it.

like image 80
Fabian Avatar answered Nov 15 '22 05:11

Fabian