I have this code below
import SwiftUI
struct MyView: View {
let text = "If you want to know more, ***[Click Here](http://example.com)*** to continue"
@Environment(\.openURL) private var openURL
var body: some View {
Text(LocalizedString(text))
.environment(\.openURL, OpenURLAction{ url in
print(url)
return .systemAction
})
}
}
I saw this in OpenURLAction Documentation and other SO questions like This answer from workingdog support Ukraine
But I always get a runtime error from Xcode saying:
Key path value type 'WritableKeyPath<EnvironmentValues, OpenURLAction>' cannot be converted to contextual type 'KeyPath<EnvironmentValues, OpenURLAction>'
Please can some one tell me what's going wrong? I'm using Xcode 14.0.1 if needed
Note: My reason for this is that the URLs associated with the text are not valid URLs, for example, I have a URL like this "[John Doe](friend-4-2)"
, so I want to open another ViewController in my app depending on the particular link the user clicked
Below is an image showing how my code looks like and the error I get
This was an odd one...
The error "Key path value type 'WritableKeyPath<EnvironmentValues, OpenURLAction>' cannot be converted to contextual type 'KeyPath<EnvironmentValues, OpenURLAction>'
" only happens in when supporting anything less than iOS 15.
That is because OpenURLAction(handler:)
is only available starting iOS 15.
https://developer.apple.com/documentation/swiftui/openurlaction/init(handler:)
If you add @available(iOS 15, *)
above the struct
the error should go away.
After that you should be able to intercept any URL
import SwiftUI
@available(iOS 15, *)
struct LinkView: View {
@State var clickedCount: Int = 0
let text = "If you want to know more, ***[Click Here](yourApp://click-here)*** to continue"
@Environment(\.openURL) private var openURL
var body: some View {
VStack{
Text("\(clickedCount)")
Text(LocalizedStringKey(text))
.environment(\.openURL, OpenURLAction { url in
clickedCount += 1
return .systemAction
})
}
}
}
@available(iOS 15, *)
struct LinkView_Previews: PreviewProvider {
static var previews: some View {
LinkView()
}
}
iOS 14 and below are not supported by this method.
But if you want to support the lower versions you can use URL Scheme
with onOpenURL(perform:)
First add the Scheme "Target > Info > URL Types"
then use the code below.
struct LinkView: View {
@State var clickedCount: Int = 0
let text = "If you want to know more, ***[Click Here](yourApp://clickHere)*** to continue"
@Environment(\.openURL) private var openURL
var body: some View {
VStack{
Text("\(clickedCount)")
Link("Click-here", destination: URL(string: "yourApp://clickHere")!)
Text(LocalizedStringKey(text))
.onOpenURL { url in
//Check the URL
if url.absoluteString.hasSuffix("clickHere") {
clickedCount += 1
}else{
print("Tried to open \n\t\(url.absoluteString)")
}
}
}
}
}