简体   繁体   中英

Swift Notification Center is causing memory leak

First time poster. I am very new to Swift and coding and general, and have run into a problem I can't seem to solve.

In my code, I have two view controllers. The first view controller allows a user to view Bluetooth devices, and select a device to connect to. When the user selects a device, it segues to the second view controller, which presents temperature data from the Bluetooth device.

This all works fine and dandy, but if I segue back to the first view controller, and then select the same device again, I now receive two of the same temperature readings from the device. (The bluetooth device is receiving two of the same commands from my code and is sending two values back).

Essentially every time I segue back and forth between view controllers, it seems that another instance of the view controller is created, thus creating a memory leak. (If I segued back and forth five times I would receive five Bluetooth readings for every one time I clicked the button to receive a value)

I believe my problem lies in my creation and dismissal of Notification Center Observers, but I can't seem to figure out the correct solution.

I left out code I felt wasn't pertinent to my problem, so if I'm missing any code necessary to solve the problem let me know. Any help would be greatly appreciated!

// First View Controller

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        print("*****************************")
        print("Connection complete")
        print("Peripheral info: \(String(describing: blePeripheral))")

        //Stop Scan- We don't need to scan once we've connected to a peripheral. We got what we came for.
        centralManager?.stopScan()
        print("Scan Stopped")

        //Erase data that we might have
        data.length = 0

        //Discovery callback
        peripheral.delegate = self
        //Only look for services that matches transmit uuid
        peripheral.discoverServices(nil)

        performSegue(withIdentifier: "Go", sender: nil)
    }


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let destination = segue.destination as! TempPage
        destination.peripheral = blePeripheral
    }



func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

        if characteristic == rxCharacteristic {
            if let ASCIIstring = NSString(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue) {
                characteristicASCIIValue = ASCIIstring
                NotificationCenter.default.post(name:NSNotification.Name(rawValue: "Notify"), object: nil)
               connectionStatus = "Connected!"
            }
        }

// Second View Controller

override func viewDidLoad() {
        super.viewDidLoad()

        //Create and start the peripheral manager
        peripheralManager = CBPeripheralManager(delegate: self, queue: nil)

        //-Notification for updating the text view with incoming text
        updateIncomingData()

    }


    override func viewDidDisappear(_ animated: Bool) {
         peripheralManager?.stopAdvertising()
         self.peripheralManager = nil
         super.viewDidDisappear(animated)
         NotificationCenter.default.removeObserver(self)

    }

    func updateIncomingData () {
        NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "Notify"), object: nil , queue: nil){
            notification in

            if characteristicASCIIValue != nil
            {
            self.rawValue = characteristicASCIIValue as String
                print(characteristicASCIIValue)

            }
            self.batteryLevelLabel.text = ("\(String(batteryLevel))%")

        }

@IBAction func returnToFirstViewController(_ sender: Any) {
        navigationController?.popViewController(animated: true)
        dismiss(animated: true, completion: nil)
    }



        }

Try capturing self as unowned or weak in the notification center callback:

    func updateIncomingData () {
        NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "Notify"), object: nil , queue: nil) { [unowned self] notification in

            if characteristicASCIIValue != nil
            {
            self.rawValue = characteristicASCIIValue as String
                print(characteristicASCIIValue)

            }
            self.batteryLevelLabel.text = ("\(String(batteryLevel))%")

        }

This article might be useful: https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM