From 5b98b57af146cb56746bb39fd749b23047673d9a Mon Sep 17 00:00:00 2001 From: TizianoCoroneo <15340382+TizianoCoroneo@users.noreply.github.com> Date: Mon, 20 Jul 2026 13:14:21 +0200 Subject: [PATCH] Fix Mac Catalyst build by gating AppKit code on os(macOS) Mac Catalyst reports both os(iOS) and canImport(AppKit) as true, so the mismatched conditionals collided: PlatformTypes.swift selected the UIKit family (os()-based) while ~8 other files selected the AppKit branch (canImport(AppKit)-based), calling AppKit-only APIs on UIKit types and, for the paired +AppKit/+UIKit files and InlineHostingAttachment's twin #if blocks, compiling both branches at once into duplicate declarations. Replace every `#if canImport(AppKit)` with `#if os(macOS)` so the whole codebase gates on one axis: macOS => AppKit, everything else (incl. Catalyst) => UIKit. UIKit/#else branches are unchanged. Add a Build workflow that compiles the package for macOS, iOS, and Mac Catalyst so the fix stays green. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/build.yaml | 37 +++++++++++++++++++ .../AttributeContainer++.swift | 2 +- .../InlineHostingAttachment.swift | 6 +-- .../RichTextAttributes.swift | 2 +- .../InlineAttachmentTextView+AppKit.swift | 2 +- .../InlineAttachmentTextView+Layout.swift | 2 +- .../Text View/InlineAttachmentTextView.swift | 4 +- .../Support/TextAttributeConverter.swift | 6 +-- .../Text View/SwiftUI/_TextView_AppKit.swift | 2 +- Sources/RichText/TextView.swift | 2 +- 10 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..e0ab52a --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,37 @@ +name: Build + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + build: + name: Build (${{ matrix.name }}) + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + include: + - name: macOS + destination: "platform=macOS" + - name: iOS + destination: "generic/platform=iOS" + - name: Mac Catalyst + destination: "generic/platform=macOS,variant=Mac Catalyst" + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest + + - name: Build + run: | + xcodebuild build \ + -scheme RichText \ + -destination "${{ matrix.destination }}" diff --git a/Sources/RichText/Attributes & Attachments/AttributeContainer++.swift b/Sources/RichText/Attributes & Attachments/AttributeContainer++.swift index 99c1d81..08a7396 100644 --- a/Sources/RichText/Attributes & Attachments/AttributeContainer++.swift +++ b/Sources/RichText/Attributes & Attachments/AttributeContainer++.swift @@ -13,7 +13,7 @@ extension AttributeContainer { mergePolicy: AttributedString.AttributeMergePolicy = .keepNew, perform transform: (NSMutableParagraphStyle) -> Void ) { - #if canImport(AppKit) + #if os(macOS) let paragraphStyle = self[keyPath: \.appKit.paragraphStyle] ?? .init() #elseif canImport(UIKit) let paragraphStyle = self[keyPath: \.uiKit.paragraphStyle] ?? .init() diff --git a/Sources/RichText/Attributes & Attachments/InlineHostingAttachment.swift b/Sources/RichText/Attributes & Attachments/InlineHostingAttachment.swift index f4d3ba3..1456828 100644 --- a/Sources/RichText/Attributes & Attachments/InlineHostingAttachment.swift +++ b/Sources/RichText/Attributes & Attachments/InlineHostingAttachment.swift @@ -17,7 +17,7 @@ final public class InlineHostingAttachment: NSTextAttachment { var rootView: AnyView var sizing: HostedAttachmentSizing - #if canImport(AppKit) + #if os(macOS) private var hostingController: NSHostingController? #endif @@ -167,7 +167,7 @@ final public class InlineHostingAttachment: NSTextAttachment { @MainActor lazy var hostingView: PlatformView = { - #if canImport(AppKit) + #if os(macOS) let hostingController = NSHostingController(rootView: hostingRootView) hostingController.sizingOptions = .intrinsicContentSize self.hostingController = hostingController @@ -190,7 +190,7 @@ final public class InlineHostingAttachment: NSTextAttachment { self.replacement = attachment.replacement self.sizing = attachment.sizing - #if canImport(AppKit) + #if os(macOS) hostingController?.rootView = hostingRootView #elseif canImport(UIKit) hostingController?.rootView = hostingRootView diff --git a/Sources/RichText/Attributes & Attachments/RichTextAttributes.swift b/Sources/RichText/Attributes & Attachments/RichTextAttributes.swift index 5ba4a5a..7b80898 100644 --- a/Sources/RichText/Attributes & Attachments/RichTextAttributes.swift +++ b/Sources/RichText/Attributes & Attachments/RichTextAttributes.swift @@ -9,7 +9,7 @@ import Foundation extension AttributeScopes { struct RichTextAttributes : AttributeScope { - #if canImport(AppKit) + #if os(macOS) let appKit: AttributeScopes.AppKitAttributes #else let uiKit: AttributeScopes.UIKitAttributes diff --git a/Sources/RichText/Text View/InlineAttachmentTextView+AppKit.swift b/Sources/RichText/Text View/InlineAttachmentTextView+AppKit.swift index fb7e766..1bd94c5 100644 --- a/Sources/RichText/Text View/InlineAttachmentTextView+AppKit.swift +++ b/Sources/RichText/Text View/InlineAttachmentTextView+AppKit.swift @@ -5,7 +5,7 @@ // Created by Yanan Li on 2026/6/20. // -#if canImport(AppKit) +#if os(macOS) import AppKit diff --git a/Sources/RichText/Text View/InlineAttachmentTextView+Layout.swift b/Sources/RichText/Text View/InlineAttachmentTextView+Layout.swift index 1fc5540..f0c492c 100644 --- a/Sources/RichText/Text View/InlineAttachmentTextView+Layout.swift +++ b/Sources/RichText/Text View/InlineAttachmentTextView+Layout.swift @@ -42,7 +42,7 @@ extension InlineAttachmentTextView { cachedContentHeight = nil invalidateIntrinsicContentSize() - #if canImport(AppKit) + #if os(macOS) needsLayout = true setNeedsDisplay(bounds) #elseif canImport(UIKit) diff --git a/Sources/RichText/Text View/InlineAttachmentTextView.swift b/Sources/RichText/Text View/InlineAttachmentTextView.swift index 4ebe8fe..ef044ab 100644 --- a/Sources/RichText/Text View/InlineAttachmentTextView.swift +++ b/Sources/RichText/Text View/InlineAttachmentTextView.swift @@ -159,7 +159,7 @@ fileprivate extension NSMutableAttributedString { options: [] ) { attrs, range, _ in if attrs[.foregroundColor] == nil { - #if canImport(AppKit) + #if os(macOS) addAttribute(.foregroundColor, value: NSColor.labelColor, range: range) #elseif canImport(UIKit) addAttribute(.foregroundColor, value: UIColor.label, range: range) @@ -170,7 +170,7 @@ fileprivate extension NSMutableAttributedString { func _fixFont(_ font: PlatformFont?, in range: NSRange) { let font: PlatformFont = font ?? { - #if canImport(AppKit) + #if os(macOS) return NSFont.systemFont(ofSize: NSFont.systemFontSize) #elseif canImport(UIKit) return UIFont.preferredFont(forTextStyle: .body) diff --git a/Sources/RichText/Text View/Support/TextAttributeConverter.swift b/Sources/RichText/Text View/Support/TextAttributeConverter.swift index 9209e3d..8232a61 100644 --- a/Sources/RichText/Text View/Support/TextAttributeConverter.swift +++ b/Sources/RichText/Text View/Support/TextAttributeConverter.swift @@ -8,7 +8,7 @@ import CoreText import SwiftUI -#if canImport(AppKit) +#if os(macOS) typealias ViewRepresentable = NSViewRepresentable typealias RepresentableContext = NSViewRepresentableContext typealias PlatformColor = NSColor @@ -126,7 +126,7 @@ enum TextAttributeConverter { var attributes = AttributeContainer() if intent.contains(.strikethrough) { - #if canImport(AppKit) + #if os(macOS) attributes.appKit.strikethroughStyle = .single #elseif canImport(UIKit) attributes.uiKit.strikethroughStyle = .single @@ -151,7 +151,7 @@ enum TextAttributeConverter { _ textView: PlatformTextView, configuration: TextViewRenderConfiguration ) { - #if canImport(AppKit) + #if os(macOS) textView.baseWritingDirection = NSWritingDirection(configuration.layoutDirection) textView.alignment = NSTextAlignment( configuration.multilineTextAlignment, diff --git a/Sources/RichText/Text View/SwiftUI/_TextView_AppKit.swift b/Sources/RichText/Text View/SwiftUI/_TextView_AppKit.swift index 446c2b2..10fe7f9 100644 --- a/Sources/RichText/Text View/SwiftUI/_TextView_AppKit.swift +++ b/Sources/RichText/Text View/SwiftUI/_TextView_AppKit.swift @@ -5,7 +5,7 @@ // Created by Yanan Li on 2025/8/24. // -#if canImport(AppKit) +#if os(macOS) import SwiftUI struct _TextView_AppKit: NSViewRepresentable { diff --git a/Sources/RichText/TextView.swift b/Sources/RichText/TextView.swift index f2af496..a04e32d 100644 --- a/Sources/RichText/TextView.swift +++ b/Sources/RichText/TextView.swift @@ -74,7 +74,7 @@ public struct TextView: View { } public var body: some View { - #if canImport(AppKit) + #if os(macOS) _TextView_AppKit(content: content) #elseif canImport(UIKit) _TextView_UIKit(content: content)