Является ли протокол ссылочным или типом значения в Swift? - PullRequest
0 голосов
/ 02 сентября 2018

Причина, по которой я задаю этот вопрос, заключается в том, что я читаю учебник, в котором используется делегирование. На основании того, что я прочитал из других уроков / статей в Интернете, насколько мне известно, этот конкретный учебник не создал цикл сохранения. Я также проверил это с помощью инструментов (утечки памяти и зомби), чтобы убедиться, что не было утечки памяти.

Я пытаюсь выяснить, должен ли класс просто соответствовать протоколу, это создает ссылку?

Не думаю, что это так, но я хочу быть уверенным.

Вот протокол и класс, который создает член делегата:

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

}

Вот контроллер представления, который соответствует протоколу, но также имеет свойство класса класса, упомянутого выше. Я еще не уверен, почему этот контроллер представления соответствует протоколу, но я не думаю, что это должно увеличить счетчик ссылок:

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

}

1 Ответ

0 голосов
/ 02 сентября 2018

Не думаю, что это должно увеличить счетчик ссылок:

var transferServiceScanner: TransferServiceScanner увеличивает количество ссылок до единицы, поскольку все ссылки являются сильными, если они не объявлены слабыми или что-либо еще.

Хранение переменной делегата как weak гарантирует, что сильные ссылки не идут в обе стороны, и поэтому ARC может их деиницировать.

Я пытаюсь выяснить, должен ли класс просто соответствовать протоколу, создает ли это ссылку?

Класс всегда является ссылочным типом, независимо от того, ссылаетесь ли вы на него по протоколу или напрямую. Таким образом, назначение протокола с ссылочным типом (классом) позади него не копирует объект класса, но вы скорее выдаете другую ссылку на объект и увеличиваете счетчик ссылок, на который смотрит ARC.

С

protocol TransferServiceScannerDelegateProtocol: NSObjectProtocol {

вы убедитесь, что только класс может реализовать протокол, поэтому вы можете объявить weak var delegate: TransferServiceScannerDelegateProtocol, потому что только классы могут реализовать NSObjectProtocol с NSObject & co.

Не объявляя протокол только для класса, либо структура, либо класс, оба могут реализовывать протокол. Но только если вы ограничите протокол только для класса, вы можете использовать протокол, как если бы он был классом, используя с ним такие вещи, как weak.

...