Is a protocol either a reference or value type in Swift?
Asked Answered
G

1

7

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.
    }
    */

}
Gareri answered 2/9, 2018 at 16:38 Comment(4)
I'm not sure yet as to why this view controller conforms to the protocol it’s unclear what you mean.Pandora
Well So far we have placed the protocol functions inside this view controller however I believe that since the TransferServiceScanner class already has a variable of this protocol type then I don't think its necessary. I don't think its necessary because the view controller creates a TransferServiceScanner type property.Gareri
I believe that since the TransferServiceScanner class already has a variable of this protocol type then I don't think its necessary. you can only use a type as a protocol if the type conforms to the protocol, and conformance has to be declared, whether the type implements the necessary methods already or not. If you don’t declare the view controller to conform, then you can’t treat it as the delegate since you can’t give it to the service scanner, since that expects an object conforming to the protocol.Pandora
You're right, it crashed after removing the conformance in the view controller.Gareri
P
3

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.

Pandora answered 2/9, 2018 at 16:56 Comment(1)
A cleaner syntax meaning exactly the same is protocol TransferServiceScannerDelegateProtocol: class {Gyral

© 2022 - 2024 — McMap. All rights reserved.