Ios Swift通知中心导致内存泄漏
第一次海报。我对Swift、编码和通用性非常陌生,遇到了一个我似乎无法解决的问题 在我的代码中,我有两个视图控制器。第一视图控制器允许用户查看蓝牙设备,并选择要连接的设备。当用户选择设备时,它会转到第二视图控制器,该控制器显示来自蓝牙设备的温度数据 这一切都很好,但如果我回到第一个视图控制器,然后再次选择相同的设备,我现在会从该设备收到两个相同的温度读数。(蓝牙设备从我的代码中接收到两个相同的命令,并返回两个值) 实际上,每次我在视图控制器之间来回切换时,似乎都会创建视图控制器的另一个实例,从而造成内存泄漏。(如果我前后切换五次,每次单击按钮接收值时,我将收到五个蓝牙读数) 我相信我的问题在于我创建和解雇了通知中心观察员,但我似乎无法找到正确的解决方案 我遗漏了我觉得与我的问题无关的代码,所以如果我遗漏了解决问题所需的任何代码,请告诉我。任何帮助都将不胜感激 //第一视图控制器Ios Swift通知中心导致内存泄漏,ios,swift,memory,bluetooth,notifications,Ios,Swift,Memory,Bluetooth,Notifications,第一次海报。我对Swift、编码和通用性非常陌生,遇到了一个我似乎无法解决的问题 在我的代码中,我有两个视图控制器。第一视图控制器允许用户查看蓝牙设备,并选择要连接的设备。当用户选择设备时,它会转到第二视图控制器,该控制器显示来自蓝牙设备的温度数据 这一切都很好,但如果我回到第一个视图控制器,然后再次选择相同的设备,我现在会从该设备收到两个相同的温度读数。(蓝牙设备从我的代码中接收到两个相同的命令,并返回两个值) 实际上,每次我在视图控制器之间来回切换时,似乎都会创建视图控制器的另一个实例,从而
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!"
}
}
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)
}
}
//第二视图控制器
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!"
}
}
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)
}
}
尝试在notification center回调中将self捕获为无主或弱:
func updateIncomingData(){
NotificationCenter.default.addObserver(forName:NSNotification.Name(rawValue:“Notify”),对象:nil,队列:nil){
如果特征为SCIVALUE!=无
{
self.rawValue=characteristicascivalue作为字符串
印刷品(特征科学版)
}
self.batteryLevelLabel.text=(“\(字符串(batteryLevel))%”)
}
本文可能很有用:尝试在notification center回调中将self捕获为无主或弱:
func updateIncomingData(){
NotificationCenter.default.addObserver(forName:NSNotification.Name(rawValue:“Notify”),对象:nil,队列:nil){
如果特征为SCIVALUE!=无
{
self.rawValue=characteristicascivalue作为字符串
印刷品(特征科学版)
}
self.batteryLevelLabel.text=(“\(字符串(batteryLevel))%”)
}
这篇文章可能很有用:Hi!我相信你的问题不在于NotificationController(你给出的代码似乎一切正常),而在于其他方面:我相信你在SecondViewController的某个地方有一个很强的引用循环。添加
print(self)
在您的通知观察器中,查看您将获得的所有实例的标识。我希望这会有所帮助!@NikolaRistic非常感谢您的回复!我相信您是对的,我确实在某个地方有一个很强的引用循环。很抱歉打扰您,但您能给我一个这样的示例吗?我会看看pro您的第二视图控制器的特性以及您将引用传递给第二视图控制器的位置。如果您设法找到它,则声明它弱或无主应该可以解决问题。您好!我相信您的问题不是NotificationController(您给出的代码似乎一切正常),但还有一点:我相信您的SecondViewController中有一个强大的引用循环在您的通知观察器中,查看您将获得的所有实例的标识。我希望这会有所帮助!@NikolaRistic非常感谢您的回复!我相信您是对的,我确实在某个地方有一个很强的引用循环。很抱歉打扰您,但您能给我一个这样的示例吗?我会看看pro第二视图控制器的特性以及向第二视图控制器传递引用的位置。如果您设法找到它,则将其声明为“弱”或“无主”应该可以解决此问题。