You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何为macOS创建带文本字段的提醒弹窗(可借助AppKit)

可以实现,根据项目支持的最低macOS系统版本,可选择以下两种方案:

方案1:纯SwiftUI原生实现(适用macOS 12.0及以上)

macOS 12 开始系统内置的SwiftUI alert修饰符已经原生支持内嵌文本输入控件,无需桥接AppKit,调用后会展示和系统样式完全一致的提醒弹窗,是优先推荐的实现方式。

示例代码:

import SwiftUI

struct DemoView: View {
    @State private var showInputAlert = false
    @State private var userInput = ""
    
    var body: some View {
        Button("弹出带输入框的提醒") {
            showInputAlert = true
        }
        .alert("操作提示", isPresented: $showInputAlert) {
            TextField("请输入内容", text: $userInput)
            // 如需密码输入场景,替换为SecureField即可
            // SecureField("请输入密码", text: $userInput)
            Button("确认") {
                // 在此处编写输入内容的后续处理逻辑
                print("用户输入结果:\(userInput)")
            }
            Button("取消", role: .cancel) {
                userInput = ""
            }
        } message: {
            Text("请在下方输入框填写需要提交的内容")
        }
    }
}

方案2:AppKit桥接实现(兼容全版本macOS)

如果项目需要兼容macOS 12以下的系统版本,可以通过桥接AppKit的NSAlert实现,封装为可复用的ViewModifier后调用方式和原生API几乎一致,还可以灵活自定义输入框的属性。

首先封装可复用组件:

import SwiftUI
import AppKit

struct MacInputAlertModifier: ViewModifier {
    @Binding var isPresented: Bool
    let title: String
    let message: String
    let placeholder: String
    let defaultValue: String
    let onConfirm: (String) -> Void
    
    func body(content: Content) -> some View {
        content
            .onChange(of: isPresented) { isShow in
                guard isShow else { return }
                let alert = NSAlert()
                alert.messageText = title
                alert.informativeText = message
                alert.addButton(withTitle: "确认")
                alert.addButton(withTitle: "取消")
                
                // 配置输入框
                let inputField = NSTextField(frame: NSRect(x: 0, y: 0, width: 280, height: 24))
                inputField.placeholderString = placeholder
                inputField.stringValue = defaultValue
                alert.accessoryView = inputField
                
                // 前置应用窗口并弹出模态弹窗
                NSApp.activate(ignoringOtherApps: true)
                let response = alert.runModal()
                if response == .alertFirstButtonReturn {
                    onConfirm(inputField.stringValue)
                }
                isPresented = false
            }
    }
}

extension View {
    func macInputAlert(
        isPresented: Binding<Bool>,
        title: String,
        message: String = "",
        placeholder: String = "",
        defaultValue: String = "",
        onConfirm: @escaping (String) -> Void
    ) -> some View {
        self.modifier(MacInputAlertModifier(
            isPresented: isPresented,
            title: title,
            message: message,
            placeholder: placeholder,
            defaultValue: defaultValue,
            onConfirm: onConfirm
        ))
    }
}

调用示例:

struct DemoView: View {
    @State private var showInputAlert = false
    
    var body: some View {
        Button("弹出兼容版输入弹窗") {
            showInputAlert = true
        }
        .macInputAlert(
            isPresented: $showInputAlert,
            title: "重命名",
            message: "请输入新的文件名称",
            placeholder: "例如:工作文档.md",
            defaultValue: "未命名.md"
        ) { newName in
            print("重命名结果:\(newName)")
        }
    }
}

注意事项

  • iOS端基于UIKit的实现依赖UIAlertController类,该类在macOS平台不存在,无法直接复用
  • 原生SwiftUI方案在macOS 11及以下系统会触发编译错误,部署目标低于12.0时必须使用桥接方案
  • 桥接方案中可根据需求将NSTextField替换为NSSecureTextField实现密码输入,也可添加输入校验逻辑限制输入内容格式

内容的提问来源于stack exchange,提问作者MasterMind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 13:51:27