![](/img/trans.png)
[英]How to use Combine framework NSObject.KeyValueObservingPublisher?
[英]Basic use of the Combine Framework
Swift 5.2 iOS 14
试图了解 SwiftUI 中的 Combine Framework 并使用我在 web 上找到的示例将此代码放在一起。但是...示例不完整。
现在,当我改变我的设备的方向时,它会写入方向,但我如何在我的主循环中使用它? 我似乎也找不到任何要订阅的东西,所以我尝试只使用 onChange。 可悲的是,这是行不通的。
class SizeClassViewV: ObservableObject {
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
enum Orientation {
case portrait
case landscape
}
@Published var orientation: Orientation = .portrait
private var listener: AnyCancellable?
init() {
if horizontalSizeClass == .compact && verticalSizeClass == .regular {
orientation = .portrait
} else if horizontalSizeClass == .regular && verticalSizeClass == .compact {
orientation = .landscape
}
listener = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
.compactMap { ($0.object as? UIDevice)?.orientation }
.compactMap { deviceOrientation -> Orientation? in
if deviceOrientation.isPortrait {
return .portrait
} else if deviceOrientation.isLandscape {
return .landscape
} else {
return nil
}
}
.assign(to: \.orientation, on: self)
}
deinit {
listener?.cancel()
}
}
在我的主循环中现在看起来像这样吗?
struct ContentView: View {
@State var orient = SizeClassViewX()
var body: some View {
Text("foo")
.onChange(of: orient.orientation) { ( _ ) in
print("changed")
}
}
}
当我改变方向时从不打印改变?
final class SizeClassViewV: ObservableObject {
enum Orientation: Equatable {
case portrait
case landscape
}
@Published var orientation: Orientation = .portrait
private var listener: AnyCancellable?
init() {
orientation = UIDevice.current.orientation.isPortrait ? Orientation.portrait : .landscape
listener = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
.compactMap { ($0.object as? UIDevice)?.orientation }
.map { $0.isPortrait ? Orientation.portrait : .landscape }
.assign(to: \.orientation, on: self)
}
deinit {
listener?.cancel()
}
}
struct ContentView: View {
@ObservedObject var orient = SizeClassViewV()
var body: some View {
Text("Hello, world!")
.padding()
.onReceive(orient.$orientation) { value in
print(value)
}
}
}
我似乎找不到要订阅的内容
如果你看一下onReceive
声明,你可以看到它接受一个 Combine Publisher
:
@inlinable public func onReceive<P>(_ publisher: P, perform action: @escaping (P.Output) -> Void) -> some View where P : Publisher, P.Failure == Never
这意味着如果你想订阅组合方式的orientation
变化,你可以只使用onReceive
并传递相关的Publisher
:
struct ContentView: View {
@State var orient = SizeClassViewV()
var body: some View {
Text("foo")
.onReceive(orient.$orientation) { _ in
print("changed")
}
}
}
它实际上以不同的方式工作 - Environment
包装器用于 SwiftUI 视图的上下文,因此请按以下演示使用:
struct ContentView: View {
@Environment(\.verticalSizeClass) var verticalSizeClass
@Environment(\.horizontalSizeClass) var horizontalSizeClass
var body: some View {
Text("foo")
.onChange(of: horizontalSizeClass) { _ in
print("horizontal class changed")
}
.onChange(of: verticalSizeClass) { _ in
print("vertical class changed")
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.