Swift package

cocoa-aliases

Cross-platform Cocoa names for compatible UIKit and AppKit types

Remove type-name conditionals from shared UI code

UIKit and AppKit often provide compatible types under different prefixes. CocoaAliases maps those pairs to stable Cocoa* names so shared extensions and infrastructure do not repeat the same declaration.

#if canImport(UIKit)
import UIKit

extension UIView {
  @discardableResult
  func hidden(_ isHidden: Bool) -> Self {
    self.isHidden = isHidden
    return self
  }
}
#elseif canImport(AppKit)
import AppKit

extension NSView {
  @discardableResult
  func hidden(_ isHidden: Bool) -> Self {
    self.isHidden = isHidden
    return self
  }
}
#endif
Before
import CocoaAliases

extension CocoaView {
  @discardableResult
  func hidden(_ isHidden: Bool) -> Self {
    self.isHidden = isHidden
    return self
  }
}
After

The public aliases cover much more than UIView and NSView:

AreaShared names
UI foundationsCocoaView, CocoaViewController, CocoaWindow, CocoaResponder
Visual valuesCocoaColor, CocoaImage, CocoaFont, CocoaFontDescriptor
ControlsCocoaButton, CocoaTextField, CocoaSlider, CocoaStackView
CollectionsCocoaCollectionView, CocoaTableView and diffable data-source aliases
LayoutCocoaLayoutGuide, CocoaLayoutPriority, CocoaDirectionalEdgeInsets
SwiftUICocoaHostingController, CocoaViewRepresentable, CocoaViewControllerRepresentable

One SwiftUI representable protocol

When a custom wrapper really needs a named representable type, conform once and implement the Cocoa-named lifecycle. The package forwards it to makeUIView / updateUIView on UIKit and makeNSView / updateNSView on AppKit.

import CocoaAliases
import SwiftUI

struct StatusView: CocoaViewRepresentable {
  var isHidden: Bool

  func makeCocoaView(context: Context) -> CocoaView {
    CocoaView()
  }

  func updateCocoaView(
    _ view: CocoaView,
    context: Context
  ) {
    view.isHidden = isHidden
  }
}
StatusView.swift

For one-off bridges, CocoaComponent removes the representable declaration entirely. _CocoaViewProtocol and _CocoaViewControllerProtocol remain available for the narrower case where an extension must use a subclass’s concrete Self in a position a class extension cannot express.

Aliases remove type-name differences – not behavioral ones. Keep conditional compilation around APIs whose signatures or lifecycle differ, and compile every supported platform before exposing an alias from public API.