Skip to content

Commit

Permalink
Bugfix: Tagview no longer errors on compile in iOS 18.1
Browse files Browse the repository at this point in the history
TagView and TagViewForScollView deprecated for Swift 6, iOS 16, macOS 13, watchOS 9, tvOS 16, visionOS 1. HFlowLayout should be used instead.
HairSpaceJustifiedText changed from iOS only to canImport(UIKit)
  • Loading branch information
ryanlintott committed Nov 5, 2024
1 parent df55c5d commit 3b1f65f
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 10 deletions.
4 changes: 2 additions & 2 deletions Example/FrameUpExample/TagViewExamples/TagViewExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import FrameUp
import SwiftUI

@available(swift, deprecated: 6.0, message: "This view may crash with Swift 6 strict concurrency due to unsafe thread jumping. Use HFlowLayout instead.")
@available(swift, deprecated: 6)
struct TagViewExample: View {
let elements = ["Thing", "Another", "Test", "Short", "Long Text is Long", "More", "Cool Tag"]

Expand All @@ -27,7 +27,7 @@ struct TagViewExample: View {
}
}

@available(swift, deprecated: 6.0, message: "This view may crash with Swift 6 strict concurrency due to unsafe thread jumping. Use HFlowLayout instead.")
@available(swift, deprecated: 6)
struct TagViewExample_Previews: PreviewProvider {
static var previews: some View {
TagViewExample()
Expand Down
6 changes: 3 additions & 3 deletions Example/FrameUpExample/TagViewExamples/TagViewExamples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import SwiftUI
struct TagViewExamples: View {
var body: some View {
Section {
#if swift(<6)
#if swift(>=6)
UnavailableView()
#else
NavigationLink(destination: TagViewExample()) {
Label("TagView", systemImage: "tag")
}

NavigationLink(destination: TagViewForScrollViewExample()) {
Label("TagViewForScrollView", systemImage: "tag.square")
}
#else
Label("Deprecated in Swift 6", systemImage: "x.circle")
#endif
} header: {
Text("TagView")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import FrameUp
import SwiftUI

@available(swift, deprecated: 6.0, message: "This view may crash with Swift 6 strict concurrency due to unsafe thread jumping. Use HFlowLayout instead.")
@available(swift, deprecated: 6)
struct TagViewForScrollViewExample: View {
let elements = ["Thing", "Another", "Test", "Short", "Long Text is Long", "More", "Cool Tag"]

Expand All @@ -35,7 +35,7 @@ struct TagViewForScrollViewExample: View {
}
}

@available(swift, deprecated: 6.0, message: "This view may crash with Swift 6 strict concurrency due to unsafe thread jumping. Use HFlowLayout instead.")
@available(swift, deprecated: 6)
struct TagViewForScrollViewExample_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Ryan Lintott on 2024-10-21.
//

#if canImport(UIKit)
import FrameUp
import SwiftUI

Expand Down Expand Up @@ -48,3 +49,4 @@ struct HairSpaceJustifiedTextExample: View {
#Preview {
HairSpaceJustifiedTextExample()
}
#endif
4 changes: 4 additions & 0 deletions Example/FrameUpExample/TextExamples/TextExamples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ import SwiftUI
struct TextExamples: View {
var body: some View {
Section {
#if canImport(UIKit)
NavigationLink(destination: HairSpaceJustifiedTextExample()) {
Label("HairSpaceJustifiedText", systemImage: "character.textbox")
}
#else
UnavailableView()
#endif

/// This check ensures this code only builds in Xcode 16+
#if compiler(>=6)
Expand Down
28 changes: 27 additions & 1 deletion Sources/FrameUp/TagView/TagView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ import SwiftUI
/// Text(element)
/// }
///
@available(swift, deprecated: 6.0, message: "This view may crash with Swift 6 strict concurrency due to unsafe thread jumping. Use HFlowLayout instead.")
@available(swift, deprecated: 6, message: "Replace with HFlowLayout and ForEach.")
@available(iOS, introduced: 14, deprecated: 16, message: "Replace with HFlowLayout and ForEach.")
@available(macOS, introduced: 11, deprecated: 13, message: "Replace with HFlowLayout and ForEach.")
@available(watchOS, introduced: 7, deprecated: 9, message: "Replace with HFlowLayout and ForEach.")
@available(tvOS, introduced: 14, deprecated: 16, message: "Replace with HFlowLayout and ForEach.")
@available(visionOS, introduced: 1, deprecated: 1, message: "Replace with HFlowLayout and ForEach.")
public struct TagView<Element: Hashable, Content: View>: View {
let elements: [Element]
let content: (Element) -> Content
Expand All @@ -29,6 +34,26 @@ public struct TagView<Element: Hashable, Content: View>: View {
self.content = content
}

#if swift(>=6)
public var body: some View {
if #available(iOS 16, macOS 13, watchOS 9, tvOS 16, *) {
HFlowLayout(alignment: .topLeading, spacing: 0) {
ForEach(elements, id: \.self) { element in
content(element)
}
}
} else {
// Fallback on earlier versions
WidthReader { width in
HFlow(alignment: .topLeading, maxWidth: width, horizontalSpacing: 0, verticalSpacing: 0) {
ForEach(elements, id: \.self) { element in
content(element)
}
}
}
}
}
#else
public var body: some View {
/// Using variables inside the view body is not recommended by Apple but it mostly works. Mutating these main actor variables from a nonisolated closure (like alignmentGuide) may cause unexpected behaviour in Swift 5 mode (but it appears to work) and will likely cause crashes in Swift 6.
var maxWidth = CGFloat.zero
Expand Down Expand Up @@ -73,4 +98,5 @@ public struct TagView<Element: Hashable, Content: View>: View {
}
}
}
#endif
}
25 changes: 24 additions & 1 deletion Sources/FrameUp/TagView/TagViewForScrollView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import SwiftUI
/// }
/// }
///
@available(swift, deprecated: 6.0, message: "This view may crash with Swift 6 strict concurrency due to unsafe thread jumping. Use HFlowLayout instead.")
@available(swift, deprecated: 6, message: "Replace with HFlowLayout and ForEach.")
@available(iOS, introduced: 14, deprecated: 16, message: "Replace with HFlowLayout and ForEach.")
@available(macOS, introduced: 11, deprecated: 13, message: "Replace with HFlowLayout and ForEach.")
@available(watchOS, introduced: 7, deprecated: 9, message: "Replace with HFlowLayout and ForEach.")
@available(tvOS, introduced: 14, deprecated: 16, message: "Replace with HFlowLayout and ForEach.")
@available(visionOS, introduced: 1, deprecated: 1, message: "Replace with HFlowLayout and ForEach.")
public struct TagViewForScrollView<Element: Hashable, Content: View>: View {
let maxWidth: CGFloat
let elements: [Element]
Expand All @@ -33,6 +38,23 @@ public struct TagViewForScrollView<Element: Hashable, Content: View>: View {
self.content = content
}

#if swift(>=6)
public var body: some View {
if #available(iOS 16, macOS 13, watchOS 9, tvOS 16, *) {
HFlowLayout(alignment: .topLeading, spacing: 0) {
ForEach(elements, id: \.self) { element in
content(element)
}
}
} else {
HFlow(alignment: .topLeading, maxWidth: maxWidth, maxItemWidth: nil, horizontalSpacing: 0, verticalSpacing: 0) {
ForEach(elements, id: \.self) { element in
content(element)
}
}
}
}
#else
public var body: some View {
/// Using variables inside the view body is not recommended by Apple but it mostly works. Mutating these main actor variables from a nonisolated closure (like alignmentGuide) may cause unexpected behaviour in Swift 5 mode (but it appears to work) and will likely cause crashes in Swift 6.
var x = CGFloat.zero
Expand Down Expand Up @@ -70,4 +92,5 @@ public struct TagViewForScrollView<Element: Hashable, Content: View>: View {
}
}
}
#endif
}
2 changes: 1 addition & 1 deletion Sources/FrameUp/Text/HairSpaceJustifiedText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import SwiftUI

#if os(iOS)
#if canImport(UIKit)
extension StringProtocol {
/// Returns the size of this string when printed in a single line in the specified font.
/// - Parameter font: Font used when measuring size.
Expand Down

0 comments on commit 3b1f65f

Please sign in to comment.