Skip to content

Commit

Permalink
feat: Add @ViewBuilder and remove optional content
Browse files Browse the repository at this point in the history
  • Loading branch information
facumenzella committed Jan 14, 2025
1 parent 35b3bca commit 9b5e964
Showing 1 changed file with 51 additions and 12 deletions.
63 changes: 51 additions & 12 deletions RevenueCatUI/CustomerCenter/Views/CompatibilityLabeledContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,72 @@ import SwiftUI

#if os(iOS)

/// A SwiftUI view for displaying labeled content
/// A SwiftUI view that displays a label and content in a layout that adapts to the iOS version.
///
/// This view is designed to be compatible with both iOS 16.0+ and earlier versions.
///
/// - Parameters:
/// - label: A closure that returns the label view, typically a `Text` or any other view.
/// - content: A closure that returns the content view
///
/// ## Usage:
/// ```swift
/// CompatibilityLabeledContent {
/// Text("Name:")
/// } content: {
/// Text("John Doe")
/// }
/// ```
///
/// ## Available Initializers:
/// - `init(_ label: String, content: @escaping () -> Content)` for easy usage with `String` labels.
/// - `init(_ label: String, content: String)` for cases where both the label and content are strings.
///
/// ## iOS 16.0 and higher:
/// Uses `LabeledContent` to display the label and content in a more advanced and consistent way.
///
/// ## Earlier OS versions:
/// Uses a simple `HStack` to display the label and content, ensuring backward compatibility.
///
/// ## Discussion:
/// Although the `label` is a closure that returns a view (`() -> Label`), it is **not marked with `@ViewBuilder`
/// intentionally** for backwards compatibility.
///
/// If you need to pass multiple views in the label, you can still compose them manually using `HStack` or other layout
/// views in the closure passed to `label`. For example:
/// ```swift
/// CompatibilityLabeledContent("Name") {
/// HStack {
/// Text("First Name")
/// Text("Last Name")
/// }
/// } content: {
/// Text("John Doe")
/// }
/// ```
@available(iOS 15.0, *)
@available(macOS, unavailable)
@available(tvOS, unavailable)
@available(watchOS, unavailable)
struct CompatibilityLabeledContent<Label: View, Content: View>: View {

let label: () -> Label
let content: (() -> Content)?
let content: () -> Content

var body: some View {
if #available(iOS 16.0, *) {
LabeledContent {
if let content {
content()
}
content()
} label: {
label()
}
} else {
HStack {
label()

if let content {
Spacer()
content()
}
Spacer()

content()
}
}
}
Expand All @@ -64,10 +103,10 @@ extension CompatibilityLabeledContent where Label == Text {
@available(macOS, unavailable)
@available(tvOS, unavailable)
@available(watchOS, unavailable)
extension CompatibilityLabeledContent where Label == Text, Content == EmptyView {
init(_ label: String) {
extension CompatibilityLabeledContent where Label == Text, Content == Text {
init(_ label: String, content: String) {
self.label = { Text(label) }
self.content = nil
self.content = { Text(content) }
}
}

Expand Down

0 comments on commit 9b5e964

Please sign in to comment.