CocoaUI

从 SwiftUI 组件获取并自定义 UIKit/Cocoa 对象。

Github issues Github forks Github stars Github top language

演示

例如,Slider 内部使用 UISlider。因此,可以通过直接引用 UISlider 对象进行自定义,如下所示。

 Slider(value: $value)
    .cocoa { slider in // UISider
        slider.setThumbImage(.init(systemName: "swift"), for: .normal)
    }

Slider

文档

对于遵循名为 DefaultCocoaViewBridging 协议的组件,您可以按如下方式获取 UIKit/Cocoa 对象。DefaultCocoaViewBridging 从 SwiftUI.View 获取 UIView 对象。相比之下,DefaultCocoaControllerBridging 获取 UIViewController 对象。
CocoaBriding 协议定义了 DefaultCocoaType。 例如,对于 Toggle,DefaultCocoaType 是 UISwitch(iOS)。 可以按如下方式处理

 Toggle("Hello", isOn: .constant(true))
    .cocoa { `switch` in
        `switch`.onTintColor = .red
    }

指定类型

但是,如果 ToggleStyle 设置为 Button,则内部使用 UIButton 而不是 UISwitch。 对于这种情况,也可以通过指定类型来检索数据,如下所示。

Toggle("Hello", isOn: .constant(true))
    .cocoa(for: UIButton.self) { button in
       button.layer.borderWidth = 1
    }

指定类型的方法在 SwiftUI.View 中定义,不需要遵循 DefaultCocoaViewBridgingDefaultCocoaControllerBridging 协议。 如果未找到指定的类型,则不会调用闭包。

支持其他组件

extension XXView: DefaultCocoaViewBridging { // confirms `DefaultCocoaViewBridging`
    public typealias DefaultCocoaViewType = XXCocoaView // UIKit/Cocoa type
}

extension YYView: DefaultCocoaViewControllerBridging { // confirms `DefaultCocoaViewControllerBridging`
    public typealias DefaultCocoaControllerType = YYCocoaViewController // UIKit/Cocoa type
}

生命周期事件修饰符

在某些 View 生命周期事件中,提供了一个修饰符来检索获得的 UIKit/Cocoa 对象。 例如,以下代码在 push 时隐藏 tabBar,并在 pop 时重新显示它。

TabView {
    NavigationView {
        List(0..<100) { i in
            NavigationLink {
                Text("Detail: \(i)")
                    .cocoa(for: CocoaViewController.self) { vc in
                        print(vc)
                    }
                    .onViewWillAppear { vc in
                        // Hide TabBar
                        vc?.tabBarController?.tabBar.isHidden = true
                    }
                    .onViewWillDisappear { vc in
                        // Show TabBar
                        vc?.tabBarController?.tabBar.isHidden = false
                    }
            } label: {
                Text("Row: \(i)")
            }
        }
    }
}

以下修饰符可用。

SwiftUI 和 Cocoa 对应表

这可能会因操作系统和使用条件而异。

SwiftUI 样式 UIKit(iOS) Cocoa(macOS) UIKit(tvOS)
ScrollView - UIScrollView NSScrollView UIScrollView
List - UICollectionView(>=iOS16) UITableView(<iOS16) NSTableView UITableView
Form - UICollectionView(>=iOS16) UITableView(<iOS16) ? UITableView
TextField - UITextField NSTextField UITextField
SecureField - UITextField NSTextField UITextField
Slider - UISlider NSSlider -
Stepper - UIStepper NSStepper -
Picker Wheel UIPickerView NSButton -
Inline UIPickerView ? UISegmentedControl
Segmented UISegmentedControl NSSegmentedControl UISegmentedControl
Menu ? NSButton -
DatePicker - UIDatePicker NSDatePicker -
MultiDatePicker - UICalendarView - -
ColorPicker - UIColorWell NSColorWell -
Toggle .switch UISwitch NSSwitch -
.button UIButton NSButton -
.checkbox - NSButton -
TextEditor - UITextView NSTextView -
Button - - NSButton -
ProgressView .linear UIProgressView NSProgressIndicator UIProgressView
.circular UIActivityIndicatorView NSProgressIndicator UIActivityIndicatorView
TabView - UITabBarController NSTabView UITabBarController
NavigationView DoubleColumn UISplitViewController NSSplitView -
Stack UINavigationController - UINavigationController
NavigationStack - UINavigationController ? UINavigationController
NavgationSplitView - UISplitViewController NSSplitView -