SwiftUI-一种展示Toast的便捷方式

24 阅读1分钟

效果

Simulator Screen Recording - iPhone 14 - 2023-09-26 at 09.05.19.gif

实现方式

为了方便使用,采用ViewModifier的方式

一、创建ViewModeifier

struct Toast: ViewModifier {
  static let showNotification = Notification.Name("Toast.showNotification")
  
  @State private var isContentShowing = false
  @State private var isPresent = false
  @State private var text = ""
  
  func body(content: Content) -> some View {
    ZStack {
      content
      if isPresent {
        Text(text)
          .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) {
              isPresent = false
            }
          }.padding(20)
          .background(Color.black.opacity(0.7))
          .foregroundColor(Color.white)
          .cornerRadius(8)
      }
    }.onAppear(perform: {
      isContentShowing = true
    }).onDisappear(perform: {
      isContentShowing = false
    }).onReceive(NotificationCenter.default.publisher(for: Toast.showNotification)) { output in
      guard let content = output.userInfo?["content"] as? String else {
        return
      }
      guard isContentShowing else {
        return
      }
      text = content
      isPresent = true
    }
  }
}

二、扩展String、View

extension String {
  func toast() {
    guard !self.isEmpty else {
      return
    }
    NotificationCenter.default.post(name: Toast.showNotification, object: nil, userInfo: ["content": self])
  }
}

extension View {
  func toastable() -> some View {
    return self.modifier(Toast())
  }
}

使用

 var body: some View {
    Button("测试Toast") {
      "我是Toast".toast()
    }.toastable()
  }

最后

还可以再优化一下,暂时提供一个简单版本。不完美,但也是可以正常使用的