Conditional Imports in Swift not working? - ios

I want to use a module (SwiftyStoreKit) which has a minimum requirement of WatchOS 6.2, however I don't want to increase my WatchOS target because I don't want to lose support for older watches. My understanding is that Swift now has conditional imports which will let you import a module only in the OS allows the import but the below code is not working? I'm still getting a compiling error "Compiling for watchOS 4.3, but module 'SwiftyStoreKit' has a minimum deployment target of watchOS 6.2:" and if I remove "import SwiftyStoreKit" the module isn't detected.
#if canImport(SwiftyStoreKit)
import SwiftyStoreKit
class SwiftyStoreKitWatchHelper {
}
#endif

Try this
#if canImport(SwiftyStoreKit)
import SwiftyStoreKit
#endif
#available(watchOS 6.2)
class SwiftyStoreKitWatchHelper {
}

Related

My project's iOS deployment target is set to iOS 9.0 and i want to integrate Reality Kit in my app for iOS 13.0 and up

RealityKit is only available on iOS 13.0 and up and when I try to integrate it to my project and run it on iOS 12.0 or below, the app crashes with abort_with_payload error.
I still want my app to run on iOS 9.0 - iOS 12.0 without the AR feature. Is there a way I can do that?
This happens because the framework RealityKit always imports even though the device does not have that framework. The solution is to make it optional based on the device you are using.
Go to you project's Build Settings.
Go to Linking -> Other linker Flags
Double click Other linker Flags values to add a new one.
Press add button then type -weak_framework RealityKit
That should do it. Enter then run your app.
Hope this helps. Happy Coding. :D
Have a look at the canImport(module) directive
#if canImport(RealityKit)
import RealityKit
#endif
#available(iOS 13.0, *)
class MyClassWhichUsesRealityKit {
func do() {
let v = ARView(frame: .zero)
}
}
Source: https://github.com/apple/swift-evolution/blob/master/proposals/0075-import-test.md

How to check, swift version for Playground?

I was just testing my code in play ground(xcode-8.2), using swift tutorial. I came across following sample code:
One-Sided Ranges
for name in names[2...] {
print(name)
}
now my play ground showing an error:
now I feel that my swift version may not be supporting this code!
I looked around this answer but it provide solution for Xcode Project only.
How do I see which version of Swift I'm using?
How can I see swift version of play ground?
Try to find out swift version using following code. (Here I tried this code with Playground of Xcode 9.3 - beta 4) and it's providing me correct answer.
#if swift(>=5.2)
print("Hello, Swift 5.2")
#elseif swift(>=5.1)
print("Hello, Swift 5.1")
#elseif swift(>=5.0)
print("Hello, Swift 5.0")
#elseif swift(>=4.1)
print("Hello, Swift 4.1")
#elseif swift(>=4.0)
print("Hello, Swift 4.0")
#elseif swift(>=3.0)
print("Hello, Swift 3.x")
#else
print("Hello, Swift 2.2")
#endif
Answer to your question: I'm not sure but according to result of above code, I can say, Latest Swift version supported by your Xcode tool becomes a version of Playground's Swift Language.
By default Playground use the Swift version based on your Xcode version
You can check the Swift version by Xcode release here
https://swift.org/download/#releases
In the terminal run
swift -version
in all probability playgrounds will be using that version

How do I import the new logging functions in iOS 10 / Sierra / Xcode 8?

There is a new logging system in iOS 10 and macOS Sierra.
But I can't seem to make it work in Xcode. os_log is not recognized, and neither is any other function / constant mentioned in the docs.
Use of unresolved identifier 'os_log'
Do I need to link a framework or import a header or something? Am I missing something obvious?
In Swift:
import os
os_log("Some message")
In Objective-C:
#import <os/log.h>
os_log(OS_LOG_DEFAULT, "Some message");

Could not build Objective-C module CoreMotion error for tvOS target

I'm getting a couple of errors when creating my tvOS target from my Sprite Kit iOS game.
The first is: Could not build Objective-C module CoreMotion
Second: Umbrella header "CoreMotion.h" not found
In order to port the game, I've selected most of my files and assets from the iOS target and checked the TVOS target.
If I comment out all of the CoreMotion code, then the errors go away. I've searched Google and here to find an answer, but didn't find anything substantial.
Anyone know how to solve this?
The problem was the tvOS doesn't support CoreMotion.
I had to use iOS specific code to make it work for all relevant code.
Like so:
#if os(iOS)
import CoreMotion
#endif
You could also make tvOS specific code:
#if os(iOS)
let gameGain: CGFloat = 2.5
#elseif os(tvOS) // tvOS
let gameGain: CGFloat = 2.0
#endif

Use UIKit conditionally in file used by Watch app

I have created a model class that I use in my iOS app and my Watch app - it is included in both targets. Now I have to use UIPasteboard in this class which is only available in UIKit, which is not available to watchOS. While I can import UIKit into this file without issue, when I go to use UIPasteboard it will not compile because the watch extension does not know about it.
How can I use UIPasteboard in a class that is available to my watch app?
I wondered if I could only run that code when the device isn't an Apple Watch by using #available, but this didn't resolve the issue.
if #available(iOS 7.0, *) {
UIPasteboard.generalPasteboard()...
//ERROR: Use of unresolved identifier 'UIPasteboard'
} else {
//don't use UIPasteboard
}
Use the existing preprocessor directive defined in Swift:
#if os(iOS)
//UIKit code here
#elseif os(watchOS)
//Watch code here
#endif
See the documentation for preprocessor directives here.
Maybe you could use an extension to factor out the UIPasteboard functionality and include the file containing the extension only in the iPhone target.
Ideally, code shared by several OS's should contain only truly shared code.
Also, if you want the conditionality, this is probably a cleaner way to do it.
There are two ways to do so.
First way is using preprocessor directives, like the following example:
#if os(iOS)
//Insert UIKit (iOS) code here
#elseif os(watchOS)
//Insert WatchKit (watchOS) code here
#endif
The second way is to determine if the code is called from the WatchKit Extension or iOS App. For example, you can set a global boolean flag to true before calling the code from WatchKit Extension, and false before calling from iOS App. Then the shared code can check the value of the flag to determine it is running on iOS or watchOS.

Resources