Xcode 8.0 CBCentralManager Issue - swift

I recently downloaded Xcode 8.0 and trying to run my previous project which uses core bluetooth.
I have enabled Use Legacy Swift Language Version in build setting for compatibility in swift 2.3
everything works, but one Issue occured,
func centralManagerDidUpdateState(central: CBCentralManager)
{
print("state is \(central.state.rawValue)")
if (central.state == CBCentralManagerState.PoweredOn)
{
self.centralManager?.scanForPeripheralsWithServices([serviceUUID], options: nil)
}
else
{
// do something like alert the user that ble is not on
}
}
previously central.state would return CBCentralManagerState type as int but now it returns CBManagerState so got an error so i changed to
if (central.state == CBManagerState.PoweredOn)
But CBManagerState is only supported in IOS 10+ but i want to build it for IOS 8.3+ so how can I change the code?
UPDATE
I also converted project to swift 3.0, but still same issue, so how can i run this project on mobiles with ios version below 10?

The simplest approach is just to use the short-hand reference to the enumeration value:
func centralManagerDidUpdateState(central: CBCentralManager)
{
print("state is \(central.state.rawValue)")
if (central.state == .PoweredOn)
{
self.centralManager?.scanForPeripheralsWithServices([serviceUUID], options: nil)
}
else
{
// do something like alert the user that ble is not on
}
}
Now your code will compile without errors or warnings and works correctly on all targets

Related

Content Previewer not loading on Xcode 12.5.1

I was working on a project the other day, and my preview stopped working. I got the error "Compiling Failed, cannot find "DataType" in scope" (all code/relationships will be shown below). I have restarted XCode a few times, and even commented out that area of code but it continues to not work, is anyone else having this problem and how can I fix it?
I am previewing a sheet called "Profile Sheet", just a standard swiftUI View, so the preview code looks like:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ProfileSheet()
}
}
In the profile sheet, it is accessing data from a static function associated with my model file (different struct, different file), the functions it is using, and the ones that define "DataType", the problematic generic are here:
static func saveData<DataType>(data: DataType, for key: String) {
defaults.setValue(data, forKey: key)
}
static func retrieveData<DataType>(defaultValue: DataType, for key: String) -> DataType {
guard let value = defaults.value(forKey: key) as? DataType else {return defaultValue}
return value
}
static func saveComplexData<DataType>(data: DataType, for key: String) where DataType: Codable {
let encodedData = try! JSONEncoder().encode(data)
defaults.setValue(encodedData, forKey: key)
}
static func retrieveComplexData<DataType>(defaultValue: DataType, for key: String) -> DataType where DataType: Codable {
guard let retrievedData = defaults.value(forKey: key) as? Data else { return defaultValue}
let decodedData = try! JSONDecoder().decode(DataType.self, from: retrievedData)
return decodedData
}
all of these function as intended, and obviously compile. Even when I run to launch the previewer and compiles my app does it builder properly, its only when it is then trying to launch the preview simulator.
Finally, I thought Id remove those functions entirely and just try to display a View that has no connection to them, so I previewed Text("test") and got the same error.
on Xcode 13 beta 3 & 4 I am able to run the simulator, but I cannot work only on those betas as they are still fairly unstable.
Any help is appreciated :)
I've seen quite a bit of weird behavior with frameworks, I think due to changes to the simulators to support Apple silicon. My temporary workaround is, in my app/extension targets, to add "arm64" to the Excluded Architectures build setting when building for the simulator (as your preview appears to be trying to do), and setting "Build Active Architecture Only" to No for all schemes. Might be worth a try.
As per triplette in apple developer answers.
Try to check it out
https://developer.apple.com/forums/thread/657913
I believe it's not an issue with your code it's an issue with Xcode due to apple silicon macs. try to do a software update and reinstall the Xcode.

Executing function for lower iOS versions

Is there an way for executing functions only for lower iOS versions.
I mean we can execute always using the available attribute for iOS versions greater than the specific one ; but is there any way to do the other way round?
It's simple. You can use this:
if #available(iOS 10, *) {} else {
print("Code only for versions below iOS 10")
}
It's really annoying to write if statement and then catch what you want in the else statement. Nevertheless you can define global function to handle all cases in one place, which is also have its own issues. Never call it with a variable! Always use hardcoded string version number to check iOS version. If you accidentally checked unhandled version, just insert it and go. fatalError() will help you.
func available(version: String) -> Bool {
switch version {
case "13.5":
if #available(iOS 13.5, *) { return true }
case "12":
if #available(iOS 12, *) { return true }
default:
fatalError("iOS \(version) is not handled. Insert:\n case \"\(version)\": \n if #available(iOS \(version), *) { return true }")
}
return false }
Usage:
if !available(version: "10") {
print("Not available")
}

How to check app for compatibility with previous macOS versions?

My app works well in macOS 10.14, but breaks in macOS 10.13. How do I debug it in Xcode, having macOS 10.14 installed? Or at least how do I know what can go wrong, maybe there is some static code check?
I guess the problem could be in this code:
private static func isSystemDarkModeEnabled() -> Bool {
let global = UserDefaults.standard.persistentDomain(forName: UserDefaults.globalDomain)
let style = global!["AppleInterfaceStyle"]
if style != nil && (style as! String).lowercased() == "dark" {
return true
}
return false
}
private class SystemDarkModeChangeObserver {
static func register() {
SystemDarkModeChangeObserver.shared = SystemDarkModeChangeObserver()
}
private static var shared: SystemDarkModeChangeObserver?
private init() {
DistributedNotificationCenter.default().addObserver(self, selector: #selector(self.onChange), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
}
#objc func onChange() {
// ...
}
}
You can change the deployment target in the general project settings. Xcode should tell you what you're using that is not available in that target.
Xcode defaults to target the version installed on your development machine.
Please delete Derived Data,
You can go to File > Workspace Settings if you are in a workspace environment or File > Project Settings for a regular project environment. Then click over the little grey arrow under Derived data section and select your project folder to delete it.
if pod are used than deintegrate and reinstalling all pod files again.
Hope this works for you!

swift 2.3 how to properly use deprecated CBCentralManagerState

I'm just converting my project to swift 2.3 (XCode 8 beta 6) and I can't figure out how to use enum CBManagerState on old iOS versions (my app has deployment target iOS7).
CBCentralManager state now uses different enum CBManagerState (it was CBCentralManagerState before).
Code below does not compile because manager.state can't be compared with deprecated enum CBCentralManagerState so what should I put into else block?
Thanks for any advise!
func isBluetoothAvailable() -> Bool {
if #available(iOS 10.0, *) {
return manager.state == CBManagerState.PoweredOn
} else {
return manager.state == CBCentralManagerState.PoweredOn
}
}
I don't know whether this is a solid solution but removing the enum type seems to work...
func isBluetoothAvailable() -> Bool {
return manager.state == .PoweredOn
}

Text Input Controller WatchKit

I am trying to use presentTextInputControllerWithSuggestions in a WatchKit app.
I am not sure where I am going wrong.
presentTextInputControllerWithSuggestions(["Hello", "Hey"], completion: {
(myString) -> Void in
println(myString)
})
From the iOS 8.2 Release Notes:
WatchKit
Known Issues
The presentTextInputControllerWithSuggestions:completion: method of
WKInterfaceController is not currently supported in iOS Simulator.
You can try by tapping on a suggestion. It should do exactly the same as dictating.
Beware, the completion returns an array and not a string.
You should do it like that
self.presentTextInputControllerWithSuggestions(["Suggestion 1", "Suggestion 2"] allowedInputMode: .Plain, completion: { (selectedAnswers) -> Void in
if reply && reply.count > 0 {
if let spokenReply = selectedAnswers[0] as? String {
println("\(spokenReply)")
}
}
})
From Apple Dev Forums
Its the same a pressing microphone on the iPhone keyboard and dictating.
The Audio goes off to apple and returns and hopefully the text you spoke is returned as a String.