Post

Replies

Boosts

Views

Activity

iOS App never gets Bluetooth connection
I am developing an iOS App for a Bluetooth peripheral using SwiftUI with Swift 5 or 6. I have a few past attempts that got so far (connected to a peripheral), and some downloaded examples that connect to peripherals. Lately (last month or so), my current attempt never gets BleManager to start, and every attempt ends at my View that says 'please enable Bluetooth'. The Xcode console is totally blank with no print outputs. Coding Assistant suggested the init() in my @main structure could contain print("App initializing"), but even that never prints. Coding Assistant suggests: "• Open your project's Info.plist in Xcode. • Make sure UIApplicationSceneManifest is present and configured for SwiftUI, not referencing any storyboard. • Ensure UIMainStoryboardFile is not present (or blank)." but there is no info.plist because it is no longer required. Downloaded sample code runs and connects to peripherals, so Bluetooth is working on my iPhone and the Bluetooth device is accessible. My older attempts used to work, but now have the same problem. All attempts have "Enable Bluetooth to connect to Device" in the Privacy - Bluetooth Info.plist setting. Something is fundamentally wrong with many different code attempts. I have searched all the various settings for mention of SwiftUI or Storyboard, but not found them in working or failing projects. The downloaded code which works has minimum deployment iOS 14.0 and Swift Compiler Language Version Swift 5. My latest code attempt has minimum deployment iOS 16 and Swift 5. All code is target device iPhone (I am testing on iPhone 16e running iOS 26.2.1) and developing with Xcode 26.2 on MacBook Air M1 running the latest Tahoe. I do a Clean Build Folder before every test, and have tried re-starting both Mac and iPhone. How can my coding fail so spectacularly?
2
0
163
Feb ’26
How to prevent singleton base class getting re-initialised
TL;DR my singleton BLEManager managing Bluetooth communication keeps getting re-initialised (see console log). How should I prevent this? Using Swift 5.9 for iOS in Xcode 15.1 My code finds multiple BT devices, and lists them for selection, also building an array of devices for reference. Most code examples connect each device immediately. I am trying to connect later, when a specific device is selected and its View opens. I pass the array index of the device to the individual Model to serve as a reference, hoping to pass that back to BLEManager to connect and do further communication. After scanning has completed, the log message shows there is 1 device in it, so its not empty. As soon as I try and pass a reference back to BLEManager, the app crashes saying the array reference is out of bounds. The log shows that BLEManager is being re-initialised, presumably clearing and emptying the array. How should I be declaring the relationship to achieve this? Console log showing single device found: ContentView init BLEManager init didDiscover id: 39D43C90-F585-792A-5BD6-8749BA0B5385 In didDiscover devices count is 1 stopScanning After stopScanning devices count is 1 <-- selection made here DeviceModel init to device id: 0 BLEManager init BLEManager connectToDevice id: 0 devices is empty Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range 2023-12-28 11:45:55.149419+0000 BlueTest1[20773:1824795] Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range BlueTest1App.swift import SwiftUI @main struct BlueTest1App: App { var body: some Scene { WindowGroup { ContentView(bleManager: BLEManager()) } } } ContentView.swift import SwiftUI struct TextLine: View { @State var dev: Device var body: some View { HStack { Text(dev.name).padding() Spacer() Text(String(dev.rssi)).padding() } } } struct PeripheralLineView: View { @State var devi: Device var body: some View { NavigationLink(destination: DeviceView(device: DeviceModel(listIndex: devi.id))) { TextLine(dev: devi) } } } struct ContentView: View { @StateObject var bleManager = BLEManager.shared init(bleManager: @autoclosure @escaping () -> BLEManager) { _bleManager = StateObject(wrappedValue: bleManager()) print("ContentView init") } var body: some View { VStack (spacing: 10) { if !bleManager.isSwitchedOn { Text("Bluetooth is OFF").foregroundColor(.red) Text("Please enable").foregroundColor(.red) } else { HStack { Spacer() if !bleManager.isScanning {Button(action: self.bleManager.startScanning){ Text("Scan ") } } else { Text("Scanning") } } NavigationView { List(bleManager.devices) { peripheral in PeripheralLineView(devi: peripheral) }.frame(height: 300) } } } } } //@available(iOS 15.0, *) struct DeviceView: View { var device: DeviceModel var body: some View { ZStack { VStack { Text("Data Window") Text("Parameters") } }.onAppear(perform: { device.setUpModel() }) } } BLEManager.swift import Foundation import CoreBluetooth struct Device: Identifiable { let id: Int let name: String let rssi: Int let peri: CBPeripheral } class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate { static let shared: BLEManager = { let instance = BLEManager() return instance }() var BleManager = BLEManager.self var centralBE: CBCentralManager! @Published var isSwitchedOn = false @Published var isScanning = false var devices = [Device]() var deviceIds = [UUID]() private var activePeripheral: CBPeripheral! override init() { super.init() print(" BLEManager init") centralBE = CBCentralManager(delegate: self, queue: nil) } func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { isSwitchedOn = true } else { isSwitchedOn = false } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String { if !deviceIds.contains(peripheral.identifier) { print("didDiscover id: \(peripheral.identifier)") deviceIds.append(peripheral.identifier) let newPeripheral = Device(id: devices.count, name: name, rssi: RSSI.intValue, peri: peripheral) devices.append(newPeripheral) print("didDiscover devices count now \(devices.count)") } } } /// save as activePeripheral and connect func connectToDevice(to index: Int) { print("BLEManager connectToDevice id: \(index)") if devices.isEmpty {print ("devices is empty")} activePeripheral = devices[index].peri activePeripheral.delegate = self centralBE.connect(activePeripheral, options: nil) } func startScanning() { centralBE.scanForPeripherals(withServices: nil, options: nil) isScanning = true // Stop scan after 5.0 seconds let _: Timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(stopScanning), userInfo: nil, repeats: false) } @objc func stopScanning() { // need @objc for above Timer selector print("stopScanning") centralBE.stopScan() isScanning = false print("After stopScanning devices count is \(devices.count)") } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { } func disconnect(peripheral: Int) { } func discoverServices(peripheral: CBPeripheral) { } func discoverCharacteristics(peripheral: CBPeripheral) { } func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { } func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { } } DeviceModel.swift import Foundation import CoreBluetooth class DeviceModel: BLEManager { var index: Int //CBPeripheral position in found array init(listIndex: Int) { index = listIndex print("DeviceModel init to device id: \(index)") } func setUpModel() { connectToDevice(to: index) } }
4
0
1.1k
Jan ’24
Swift switch statement error Type 'Binding<T>' has no member 'member'
This error is generated at the first case statement in my example code. Type 'Binding' has no member 'atype1' If I change the order of the cases in the switch statement, it is always the first one which gives the error. In my code, if you delete the value of that first switch line, and type it in again, as soon as you have entered 'case .' the drop down menu will offer suggestions and you can see the atype1 & atype2 near the top of the list. What am I doing wrong? import SwiftUI enum AType: CaseIterable { case atype1 case atype2 case unknown // default } struct Peripheral: Identifiable { let id: Int let name: String var type: AType = .unknown } struct ContentView: View { @State private var peri = Peripheral(id: 1, name: "A") var body: some View { switch $peri.type { case .atype1: Text("Hello, $peri.name!") case .atype2: Text("Goodbye, $peri.name!") case .unknown: Text("Oh no!") } .padding() } } #Preview() { ContentView() }
2
0
863
Nov ’23
Xcode source control unknown green file. How to remove?
In a small project under Xcode source control, there is an unknown file (BlePeripheral.swift) which I can't find or delete. I did add it at one stage, but I thought I had deleted all references to it. I have done Clean Build Folder, closed the project, and closed Xcode in the hope of resolving. This is the source control panel showing the unwanted file in green. Right clicking on it does not have an option to Delete. This is the main Navigation panel which doesn't show it (so no option to delete it). It was in the Model folder. This is the search panel hoping to find it referenced somewhere and this is the Finder view of the project folder. Its not in the Assets.xcassets or Preview Content folders.
2
0
1k
Aug ’23
How to identify macOS version by looking in directories
I have an external disk which I used to boot from, but I can't remember which version of macOS is installed. Where do I look in the directories to determine which version is installed? I am not booted into it, and I don't want to boot in yet, so can't just look in About this Mac. The System folder itself is dated 22 March 2022 so it's quite recent.
2
0
1.3k
Aug ’22
iOS App never gets Bluetooth connection
I am developing an iOS App for a Bluetooth peripheral using SwiftUI with Swift 5 or 6. I have a few past attempts that got so far (connected to a peripheral), and some downloaded examples that connect to peripherals. Lately (last month or so), my current attempt never gets BleManager to start, and every attempt ends at my View that says 'please enable Bluetooth'. The Xcode console is totally blank with no print outputs. Coding Assistant suggested the init() in my @main structure could contain print("App initializing"), but even that never prints. Coding Assistant suggests: "• Open your project's Info.plist in Xcode. • Make sure UIApplicationSceneManifest is present and configured for SwiftUI, not referencing any storyboard. • Ensure UIMainStoryboardFile is not present (or blank)." but there is no info.plist because it is no longer required. Downloaded sample code runs and connects to peripherals, so Bluetooth is working on my iPhone and the Bluetooth device is accessible. My older attempts used to work, but now have the same problem. All attempts have "Enable Bluetooth to connect to Device" in the Privacy - Bluetooth Info.plist setting. Something is fundamentally wrong with many different code attempts. I have searched all the various settings for mention of SwiftUI or Storyboard, but not found them in working or failing projects. The downloaded code which works has minimum deployment iOS 14.0 and Swift Compiler Language Version Swift 5. My latest code attempt has minimum deployment iOS 16 and Swift 5. All code is target device iPhone (I am testing on iPhone 16e running iOS 26.2.1) and developing with Xcode 26.2 on MacBook Air M1 running the latest Tahoe. I do a Clean Build Folder before every test, and have tried re-starting both Mac and iPhone. How can my coding fail so spectacularly?
Replies
2
Boosts
0
Views
163
Activity
Feb ’26
How to prevent singleton base class getting re-initialised
TL;DR my singleton BLEManager managing Bluetooth communication keeps getting re-initialised (see console log). How should I prevent this? Using Swift 5.9 for iOS in Xcode 15.1 My code finds multiple BT devices, and lists them for selection, also building an array of devices for reference. Most code examples connect each device immediately. I am trying to connect later, when a specific device is selected and its View opens. I pass the array index of the device to the individual Model to serve as a reference, hoping to pass that back to BLEManager to connect and do further communication. After scanning has completed, the log message shows there is 1 device in it, so its not empty. As soon as I try and pass a reference back to BLEManager, the app crashes saying the array reference is out of bounds. The log shows that BLEManager is being re-initialised, presumably clearing and emptying the array. How should I be declaring the relationship to achieve this? Console log showing single device found: ContentView init BLEManager init didDiscover id: 39D43C90-F585-792A-5BD6-8749BA0B5385 In didDiscover devices count is 1 stopScanning After stopScanning devices count is 1 <-- selection made here DeviceModel init to device id: 0 BLEManager init BLEManager connectToDevice id: 0 devices is empty Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range 2023-12-28 11:45:55.149419+0000 BlueTest1[20773:1824795] Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range BlueTest1App.swift import SwiftUI @main struct BlueTest1App: App { var body: some Scene { WindowGroup { ContentView(bleManager: BLEManager()) } } } ContentView.swift import SwiftUI struct TextLine: View { @State var dev: Device var body: some View { HStack { Text(dev.name).padding() Spacer() Text(String(dev.rssi)).padding() } } } struct PeripheralLineView: View { @State var devi: Device var body: some View { NavigationLink(destination: DeviceView(device: DeviceModel(listIndex: devi.id))) { TextLine(dev: devi) } } } struct ContentView: View { @StateObject var bleManager = BLEManager.shared init(bleManager: @autoclosure @escaping () -> BLEManager) { _bleManager = StateObject(wrappedValue: bleManager()) print("ContentView init") } var body: some View { VStack (spacing: 10) { if !bleManager.isSwitchedOn { Text("Bluetooth is OFF").foregroundColor(.red) Text("Please enable").foregroundColor(.red) } else { HStack { Spacer() if !bleManager.isScanning {Button(action: self.bleManager.startScanning){ Text("Scan ") } } else { Text("Scanning") } } NavigationView { List(bleManager.devices) { peripheral in PeripheralLineView(devi: peripheral) }.frame(height: 300) } } } } } //@available(iOS 15.0, *) struct DeviceView: View { var device: DeviceModel var body: some View { ZStack { VStack { Text("Data Window") Text("Parameters") } }.onAppear(perform: { device.setUpModel() }) } } BLEManager.swift import Foundation import CoreBluetooth struct Device: Identifiable { let id: Int let name: String let rssi: Int let peri: CBPeripheral } class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate { static let shared: BLEManager = { let instance = BLEManager() return instance }() var BleManager = BLEManager.self var centralBE: CBCentralManager! @Published var isSwitchedOn = false @Published var isScanning = false var devices = [Device]() var deviceIds = [UUID]() private var activePeripheral: CBPeripheral! override init() { super.init() print(" BLEManager init") centralBE = CBCentralManager(delegate: self, queue: nil) } func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { isSwitchedOn = true } else { isSwitchedOn = false } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String { if !deviceIds.contains(peripheral.identifier) { print("didDiscover id: \(peripheral.identifier)") deviceIds.append(peripheral.identifier) let newPeripheral = Device(id: devices.count, name: name, rssi: RSSI.intValue, peri: peripheral) devices.append(newPeripheral) print("didDiscover devices count now \(devices.count)") } } } /// save as activePeripheral and connect func connectToDevice(to index: Int) { print("BLEManager connectToDevice id: \(index)") if devices.isEmpty {print ("devices is empty")} activePeripheral = devices[index].peri activePeripheral.delegate = self centralBE.connect(activePeripheral, options: nil) } func startScanning() { centralBE.scanForPeripherals(withServices: nil, options: nil) isScanning = true // Stop scan after 5.0 seconds let _: Timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(stopScanning), userInfo: nil, repeats: false) } @objc func stopScanning() { // need @objc for above Timer selector print("stopScanning") centralBE.stopScan() isScanning = false print("After stopScanning devices count is \(devices.count)") } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { } func disconnect(peripheral: Int) { } func discoverServices(peripheral: CBPeripheral) { } func discoverCharacteristics(peripheral: CBPeripheral) { } func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { } func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { } } DeviceModel.swift import Foundation import CoreBluetooth class DeviceModel: BLEManager { var index: Int //CBPeripheral position in found array init(listIndex: Int) { index = listIndex print("DeviceModel init to device id: \(index)") } func setUpModel() { connectToDevice(to: index) } }
Replies
4
Boosts
0
Views
1.1k
Activity
Jan ’24
Swift switch statement error Type 'Binding<T>' has no member 'member'
This error is generated at the first case statement in my example code. Type 'Binding' has no member 'atype1' If I change the order of the cases in the switch statement, it is always the first one which gives the error. In my code, if you delete the value of that first switch line, and type it in again, as soon as you have entered 'case .' the drop down menu will offer suggestions and you can see the atype1 & atype2 near the top of the list. What am I doing wrong? import SwiftUI enum AType: CaseIterable { case atype1 case atype2 case unknown // default } struct Peripheral: Identifiable { let id: Int let name: String var type: AType = .unknown } struct ContentView: View { @State private var peri = Peripheral(id: 1, name: "A") var body: some View { switch $peri.type { case .atype1: Text("Hello, $peri.name!") case .atype2: Text("Goodbye, $peri.name!") case .unknown: Text("Oh no!") } .padding() } } #Preview() { ContentView() }
Replies
2
Boosts
0
Views
863
Activity
Nov ’23
Xcode source control unknown green file. How to remove?
In a small project under Xcode source control, there is an unknown file (BlePeripheral.swift) which I can't find or delete. I did add it at one stage, but I thought I had deleted all references to it. I have done Clean Build Folder, closed the project, and closed Xcode in the hope of resolving. This is the source control panel showing the unwanted file in green. Right clicking on it does not have an option to Delete. This is the main Navigation panel which doesn't show it (so no option to delete it). It was in the Model folder. This is the search panel hoping to find it referenced somewhere and this is the Finder view of the project folder. Its not in the Assets.xcassets or Preview Content folders.
Replies
2
Boosts
0
Views
1k
Activity
Aug ’23
How to identify macOS version by looking in directories
I have an external disk which I used to boot from, but I can't remember which version of macOS is installed. Where do I look in the directories to determine which version is installed? I am not booted into it, and I don't want to boot in yet, so can't just look in About this Mac. The System folder itself is dated 22 March 2022 so it's quite recent.
Replies
2
Boosts
0
Views
1.3k
Activity
Aug ’22