SwiftUI 没有内置的方法来检测用户在摇晃设备,但是通过覆盖 UIWindow
中的 motionEnded()
并创建自定义视图修饰符来创建自己的代码并不需要太多工作。
这需要五个步骤:
UIDevice
添加扩展以跟踪将在发生摇动手势时发送的新通知。UIWindow
上创建扩展,以覆盖默认的 motionEnded()
方法。UIKit
在此处发送摇动手势,因此您应该查找发生的情况并将其转换为新的通知。onAppear()
,否则视图修饰符不能与 onReceive()
一起使用,这就是它出现在上方的原因。是的,它是空的,但是可以解决此问题。
这是一个完整的代码示例,它通过注释逐步说明了所有五个步骤:
// 发生摇动手势时我们将发送的通知。
extension UIDevice {
static let deviceDidShakeNotification = Notification.Name(rawValue: "deviceDidShakeNotification")
}
// 覆盖摇动手势的默认行为,改为发送我们的通知。
extension UIWindow {
open override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
if motion == .motionShake {
NotificationCenter.default.post(name: UIDevice.deviceDidShakeNotification, object: nil)
}
}
}
// 一个视图修改器,它检测到晃动并调用我们选择的功能。
struct DeviceShakeViewModifier: ViewModifier {
let action: () -> Void
func body(content: Content) -> some View {
content
.onAppear()
.onReceive(NotificationCenter.default.publisher(for: UIDevice.deviceDidShakeNotification)) { _ in
action()
}
}
}
// 一个View扩展,使修改器更易于使用。
extension View {
func onShake(perform action: @escaping () -> Void) -> some View {
self.modifier(DeviceShakeViewModifier(action: action))
}
}
// 响应晃动的示例视图
struct ContentView: View {
var body: some View {
Text("Shake me!")
.onShake {
print("Device shaken!")
}
}
}
如您所见,完成前四个步骤后,就可以继续向任何所需的视图添加 onShake()
修饰符,从而提供一些自定义代码以在发生摇动手势时运行–设置起来并不容易, 但是一旦完成,一切都可以很好地进行。