Search code examples
iosswiftswiftuitvos

SwiftUI Share Button between iOS and TVOS, focusable(_:onFocusChange:)' is unavailable in iOS


I'm trying to share a (custom) SwiftUI Button on iOS and TVs platforms. I already notice the buttons look very different per platform but my main issue is ".focussable". For the button to show correctly in tvOS i need to add the focussable parameter tot he button. however when building the button for an iOS platform, i get the following error:

focusable(_:onFocusChange:)' is unavailable in iOS

Code:

Button(action: {}) {
        HStack {
            if let image = icon, let uiimage = UIImage(named: image) {
                Image(uiImage: uiimage)
            }
            if let title = label {
                Text(title)
            }
        }
    }
    .focusable(true) { focused in
        withAnimation {
            self.background(Color.purple)
        }
    }

How can I use focussable on this button and still keep it shared between iOS and tvOS?


Solution

  • You need to use conditional compilation for such cases. For better reusability to is possible to wrap it in view modifier, like

    struct DemoFocusableModifier: ViewModifier {
        private let isFocusable: Bool
        private let onFocusChange: (Bool) -> Void
    
        init (_ isFocusable: Bool = true, onFocusChange: @escaping (Bool) -> Void = { _ in }) {
            self.isFocusable = isFocusable
            self.onFocusChange = onFocusChange
        }
    
        @ViewBuilder
        func body(content: Content) -> some View {
    #if os(tvOS)
            content
                .focusable(isFocusable, onFocusChange: onFocusChange)
    #else
            content
    #endif
        }
    }
    

    and use (instead of your .focusable) as

      }
      .modifier(DemoFocusableModifier { focused in
            // content here
      })
    
    

    Prepared with Xcode 13 / iOS 15