Neshat Neshat - 4 years ago 220
Swift Question

Will attempt to recover by breaking constraint <NSLayoutConstraint:0x17008b130 UILabel

I am connecting my swift app to a bluetooth low energy peripheral. I am very new in Swift and my problem is completely related to swift coding not BLE.

I listen for the peripheral to see if the button is pressed or not. I defined a label and assigned a text to it. when app detected a button press, I want label test to change, but instead my app crashes.

you can see my code here:

import CoreBluetooth
import UIKit

class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {

var manager:CBCentralManager!
var peripheral:CBPeripheral!
@IBOutlet weak var statusLabel: UILabel!


let BEAN_NAME = "Security Tag"
let BEAN_SCRATCH_UUID = CBUUID(string: "00001C0F-D102-11E1-9B23-000EFB0000A7")
let BEAN_SERVICE_UUID = CBUUID(string: "00001c00-d102-11e1-9b23-000efb0000a7")

override func viewDidLoad() {
super.viewDidLoad()
manager = CBCentralManager(delegate: self, queue: nil)
}

func centralManagerDidUpdateState(_ central:CBCentralManager) {
if central.state == CBManagerState.poweredOn {
central.scanForPeripherals(withServices: nil, options: nil)
debugPrint("Searching ...")
} else {
debugPrint("Bluetooth not available.")
}
}

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
let device = (advertisementData as NSDictionary).object(forKey: CBAdvertisementDataLocalNameKey) as? NSString

if device?.contains(BEAN_NAME) == true {
debugPrint("Found Bean.")

self.manager.stopScan()
self.peripheral = peripheral
self.peripheral.delegate = self

manager.connect(peripheral, options: nil)
}
}

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
debugPrint("Getting services ...")
peripheral.discoverServices(nil)
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
for service in peripheral.services! {
let thisService = service as CBService

debugPrint("Service: ", service.uuid)

if service.uuid == BEAN_SERVICE_UUID {
debugPrint("Using scratch.")
peripheral.discoverCharacteristics(nil, for: thisService)
}
}
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
debugPrint("Enabling ...")

for characteristic in service.characteristics! {
let thisCharacteristic = characteristic as CBCharacteristic

debugPrint("Characteristic: ", thisCharacteristic.uuid)

if thisCharacteristic.uuid == BEAN_SCRATCH_UUID {
debugPrint("Set to notify: ", thisCharacteristic.uuid)

// Prepare to show data

self.peripheral.setNotifyValue(true, for: thisCharacteristic)
}
}
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if characteristic.uuid == BEAN_SCRATCH_UUID {
let content = String(data: characteristic.value!, encoding: String.Encoding.utf8)

debugPrint("Notified.")
self.statusLabel.text = "Your Purchase is Registered."

}
}

func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
debugPrint("Disconnected.")

central.scanForPeripherals(withServices: nil, options: nil)

// Hide respective user interface
}

}


line that says : self.statusLabel.text = "Your Purchase is Registered."

is where I get the exception.

and this is errors I get:

2017-02-06 13:42:19.825869 kevinbletest[2143:695095] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x17008b130 UILabel:0x11dd0cbf0'Waiting for a Purchase Co...'.width == 270 (active)>",
"<NSLayoutConstraint:0x17008b770 UILabel:0x11dd0cbf0'Waiting for a Purchase Co...'.centerX == UIView:0x11dd0c850.centerX (active)>",
"<NSLayoutConstraint:0x17008b7c0 UILabel:0x11dd0cbf0'Waiting for a Purchase Co...'.leading == UIView:0x11dd0c850.leadingMargin + 50 (active)>",
"<NSLayoutConstraint:0x17408c3f0 'UIView-Encapsulated-Layout-Width' UIView:0x11dd0c850.width == 375 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x17008b130 UILabel:0x11dd0cbf0'Waiting for a Purchase Co...'.width == 270 (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
fatal error: unexpectedly found nil while unwrapping an Optional value
2017-02-06 13:42:25.299886 kevinbletest[2143:695095] fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)

Answer Source

From what I have read the error lies in here:

<NSLayoutConstraint:0x17008b130 UILabel:0x11dd0cbf0'Waiting for a Purchase Co...'.width == 270   (active)>

If you read it down below it seems that NSLayout is trying to center the label with width of 270 and fails since your text is larger than 270.

Further below it says that your app crashes because you label is actually nil.

Try printf(self.myLabel) to see if it is nil.

Your label could be nil if you added it in storyboard and you press the button before the viewDidAppear finishes.

Also try it without any constrains. Just remove the constrains. + Wait until the ViewController loads up (viewDidAppear) and then click.

You app crashes because it is unwrapping an optinal value which is nil, not because of the constrains.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download