2

I have a project that needs to support an old version of iOS and I'm trying to use SwiftUI for a view that will only appear when the user is on iOS 13 or later. The SwiftUI Preview in Xcode works just fine, but when I extend a SwiftUI struct (such as View), the project will compile and run on a device, but the Preview Canvas crashes, stating that it Failed to build myView.swift. When I click on the "diagnostics" button, it tells me that 'View' is only available in iOS 13.0 or newer and add @available attribute to enclosing extension. However, the extension in question already has @available(iOS 13.0, *) before it. For example:

@available(iOS 13.0, *)
extension View {
    func myFunc() {

    }
}

In an effort to find the root of this problem, I noticed that the preview won't crash if it's completely empty. Only once I add a function or static property to it will the canvas crash. I have also tried adding the @available line before each function in the extension, rebooting my computer, and deleting the DerivedData folder, but it doesn't seem to have made a difference.

2 Answers 2

2

You don't need @available(iOS 13.0, *) your app won't run on any device below version 13.0 so basically the error is stating this is redundant. Removing it should fix your issue.

However if you are doing SwiftUI weak linking and this issue is there then it's a known bug with xCode. If no weak linking then please remove @available(iOS 13.0, *)

EDIT: it seems like you have weak linking.

  1. Make sure SwiftUI.framework is set to optional in Build Phases -> Link Binary With Libraries

  2. Make sure your @available(iOS 13.0, *) is on top of your body not on top of your extension

example:

struct TestView2: View {
    @available(iOS 13.0, *)
    var body: some View {
        Text("test")
    }
}

extension TestView2 {
    func abc() {

    }
}

struct TestView2_Previews: PreviewProvider {
    @available(iOS 13.0, *)
    static var previews: some View {
        TestView2()
    }
}
Sign up to request clarification or add additional context in comments.

8 Comments

The app is targeting an older version of iOS, but the view in question is only meant to appear if the user is running 13.0 or later. Without @available(iOS 13.0, *) , the app wouldn't compile at all.
Got it, I edited my answer to reflect. Please check it.
I am using weak linking, and I added @available(iOS 13.0, *) to the top of my body, (instead of above the struct), but it still doesn't work. As you mentioned, this appears to be an Xcode bug, so I can only hope it gets fixed soon.
The above code works fine for me, I am able to preview and I have targeted iOS 12.4. Anyways, if there is anything else I can help you with please let me know.
It could be that the issue is that I'm trying to extend SwiftUI's built-in View struct, while your code is extending TestView2.
|
0

Discussion

The following code example works well for me. Please note the @available(iOS 13.0, *) declaration attributes for not only the View extension, but also for:

  1. The ContentView struct, which conforms to the View protocol,

and

  1. The ContentView_Previews struct, which conforms to the PreviewProvider protocol.

FYI: I set my Xcode Project's deployment target to iOS 12.4 for my test.

Code Example

import SwiftUI

@available(iOS 13.0, *)
extension View {
    func overlayText<Content>(_ content: Content) -> some View where Content : StringProtocol {
        overlay(Text(content))
    }
}

@available(iOS 13.0, *)
struct ContentView: View {
    static private var initialGreeting = "Hello World!"
    static private var greetings: [String] {
        [
            initialGreeting,
            "Hey Everyone!",
            "Hi Everybody!",
            "Hello Friends!"
            
        ]
    }
    @State private var greeting = initialGreeting
    
    var body: some View {
        Button(action: { [greeting] in
            while self.greeting == greeting {
                self.greeting = Self.greetings.randomElement()!
            }
        }) {
            Color.green
                .overlayText(greeting)
                .cornerRadius(30)
                .padding(5)
        }
        .background(Color.black)
        .frame(height: 50)
        .foregroundColor(.white)
        .font(.system(size: 28, weight: .bold))
        .cornerRadius(30)
        .padding()
    }
}

@available(iOS 13.0, *)
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.