Swift if #available not working as expected? - swift

I have a shared framework that runs in both iOS and MacOS, and I've run into a situation where in MacOS Catalina I need to make an extra check. I thought that by using the swift #available this would work:
if #available(OSX 10.15, *){
/// My Catalina Code
}
The truth is that this code passes in iOS. Would this be a bug, or is it not expected to be used this way ?

If you look through Apple documentation it should be like that.
if #available(macOS 10.15, *){
/// My Catalina Code
}

it should look like this:
if #available(macCatalyst 10.15, *) {
// use 10.15
} else {
}
if your using Catalyst.
other than that there is nothing that shows why your code snippet doesn't work.

You may need to use conditional compiling together with #available:
#if os(macOS)
if #available(macOS 15.0, *) {
//...
}
#endif
Or an ugly workaround:
if #available(macOS 15.0, iOS 9999.99, *) {
//...
}

Related

How to enable Dark theme for iOS 12 and lower

I have already added support for iOS13 where there are two switches: first one for the automatic, system based theme and the other switch to turn on and off dark theme and am switching it with the given method:
func changeThemeTo(theme: String){
switch theme {
case "dark":
UIApplication.shared.windows.forEach { window in
if #available(iOS 13.0, *) {
window.overrideUserInterfaceStyle = .dark
} else {
// Fallback on earlier versions
}
}
case "light":
UIApplication.shared.windows.forEach { window in
if #available(iOS 13.0, *) {
window.overrideUserInterfaceStyle = .light
} else {
// Fallback on earlier versions
}
}
case "auto":
UIApplication.shared.windows.forEach { window in
if #available(iOS 13.0, *) {
window.overrideUserInterfaceStyle = .unspecified
} else {
// Fallback on earlier versions
}
}
default: break
}
}
And everything is working fine for iOS 13, but now I need to enable this to work for iOS lower than 13. Is there something I can do similar to window.overrideUserInterfaceStyle = .dark or should I completely change the switching logic as did on https://www.onswiftwings.com/posts/dark-mode/

How to have different toggle style for iOS and macOS

I'm trying to have toggle with native style for iOS (switch) and macOS (checkbox) in my universal app. This code does not work:
#if targetEnvironment(macCatalyst)
private let toggleStyle = CheckboxToggleStyle()
#else
private let toggleStyle = SwitchToggleStyle()
#endif
'CheckboxToggleStyle' is unavailable in iOS
Was thinking that macros should compile correct path for each target.
CheckboxToggleStyle is for macOS only... see below API declaration. macCatalyst is actually environment simulating iOS on macOS, but from API perspective it is iOS
/// A `ToggleStyle` represented by a leading checkbox.
#available(OSX 10.15, *)
#available(iOS, unavailable)
#available(tvOS, unavailable)
#available(watchOS, unavailable)
public struct CheckboxToggleStyle : ToggleStyle {

swift: ios13 status bar setting error occurs in SideMenu library

I introduced SideMenu in CocoaPods, but an error occurs in the ios13 part of the status bar.But I don't know the correct code.
Would you please teach me?
var statusBarFrame: CGRect {
if #available(iOS 13.0, *) {
// How to do for iOS 13??
} else {
return UIApplication.shared.statusBarFrame
}
}
statusBarFrame has been deprecated in iOS 13,
for iOS 13 you can use this
var statusBarFrame: CGRect {
if #available(iOS 13.0, *) {
return UIApplication.shared.keyWindow!.windowScene!.statusBarManager!.statusBarFrame
} else {
return UIApplication.shared.statusBarFrame
}
}

How to detect iOS11 programmatically in Swift?

I saw in the WWDC video that there's some new swift function to detect iOS 11 availability.
How do I detect iOS11 with Swift?
Swift 3:
if #available(iOS 11.0, *) {
// Running iOS 11 OR NEWER
} else {
// Earlier version of iOS
}
More information is available in Declaration Attributes section of Apple's Swift Programming Guide.
Objective C:
if (#available(iOS 11, *)) {
// Running iOS 11 OR NEWER
} else {
// Earlier version of iOS
}

Is it possible to simulate device orientation in a playground?

Given this scenario:
XCPlaygroundPage.currentPage.liveView = TableViewController()
Would it be possible to simulate the device's orientation?
Based on some logic found in here the KIF testing framework, I suppose it should be possible.
The Objective-C code behind the link looks like this:
- (void)simulateDeviceRotationToOrientation:(UIDeviceOrientation)orientation
{
[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation] forKey:#"orientation"];
}
The Swift equivalent of this code would look like this:
func simulateDeviceRotation(toOrientation orientation: UIDeviceOrientation) {
let orientationValue = NSNumber(integer: orientation.rawValue)
UIDevice.currentDevice().setValue(orientationValue, forKey: "orientation")
}
And then we'd just call it something like this:
simulateDeviceRotation(toOrientation: .LandscapeLeft)
Or perhaps we want a function that runs some code for each orientation?
func forEachOrientation(block: () -> Void) {
for orientation in [UIDeviceOrientation.Portrait, UIDeviceOrientation.LandscapeLeft, UIDeviceOrientation.PortraitUpsideDown, UIDeviceOrientation.LandscapeRight] {
simulateDeviceRotation(toOrientation: orientation)
block()
}
}
And we can just call it like this:
forEachOrientation {
// do a thing
}
From my experience, this actually doesn't seem to work on iOS 9 simulators, but it does work on iOS 8 simulators. I don't know whether or not this would work on real devices.