Eric.18
Eric.18

Reputation: 473

Converting CBUUID to String in Swift

I am scanning for BlueTooth devices. I want to log them in an array of strings. I want to be able to save them but get the following errors:

Could not cast value of type 'CBUUID' (0x1f2760918) to 'NSString' (0x1f26a42d0).

CoreBT[9728:3053605] Could not cast value of type 'CBUUID' (0x1f2760918) to 'NSString' (0x1f26a42d0).

I have the following code below. There is no reference to an array as I can't even get it to a string.

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    
    if let peripheralName = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
        
        
        print("peripheral Name: \(peripheralName)")

        let uniqueID = (advertisementData["kCBAdvDataServiceUUIDs"] as! NSArray).firstObject! as! String 
        // The above line produces an error
        //Removing as! String will work prevent error but still cannot get from "any" to "string"
        
        let x = advertisementData
        print("x: \(x)")
        let y = advertisementData["kCBAdvDataServiceUUIDs"]
        print("y: \(y)")
        
        print("uniqueID: \(uniqueID)")
        self.UIDCountNumber = UIDCountNumber + 1
        self.UID_Count.text = String(self.UIDCountNumber)//label counting devices
        
        
        self.last_UID.text = uniqueID as? String //Label is not changing
        
    }
}

Any thoughts on getting these as strings so I can store them in an array?

Upvotes: 2

Views: 4678

Answers (3)

mag_zbc
mag_zbc

Reputation: 6982

The line

let uniqueID = (advertisementData["kCBAdvDataServiceUUIDs"] as! NSArray).firstObject! as! String

produces a crash because the UUID is not of String type but of completely unrelated CBUUID type. You can extract UUID string from CBUUID like so

guard let uuids = advertisementData["kCBAdvDataServiceUUIDs"] as? [CBUUID] else { return }
guard let uniqueID = uuids.first?.uuidString else { return }

Also, give up force cast operator - as!. This is a really bad practice. Use guard statements or optional chaining

Upvotes: 6

David Pasztor
David Pasztor

Reputation: 54706

The issue is that the Service UUIDs are of type CBUUID, so you should cast to [CBUUID] instead of NSArray<String>. Btw it's a better idea to use the CB...Key constants instead of String literals when retrieving values from advertisementData.

Once you have a single CBUUID instance, you can use uuidString to convert it to a String and display it on a UILabel.

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {

    if let peripheralName = advertisementData[CBAdvertisementDataLocalNameKey] as? String {

        print("peripheral Name: \(peripheralName)")
        guard let uniqueIDs = advertisementData[CBAdvertisementDataServiceUUIDsKey] as? [CBUUID], let uniqueID = uniqueIDs.first else { return }

        let x = advertisementData
        print("x: \(x)")
        let y = advertisementData["kCBAdvDataServiceUUIDs"]
        print("y: \(y)")

        print("uniqueID: \(uniqueID)")
        self.UIDCountNumber = UIDCountNumber + 1
        self.UID_Count.text = String(self.UIDCountNumber)//label counting devices


        self.last_UID.text = uniqueID.uuidString

    }
}

Unrelated to your issue, but you should also conform to the Swift naming convention, which is lowerCamelCase for variable names (uidCountNumber, uidCount and lastUID).

Upvotes: 4

CodeBender
CodeBender

Reputation: 36612

Apple provides an API for getting the string:

https://developer.apple.com/documentation/corebluetooth/cbuuid/1518742-uuidstring

var uuidString: String { get }

Upvotes: 6

Related Questions