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

SwiftUI中实现仅支持Emoji输入的文本框:给定EmojiTextField代码适用性及使用方案咨询

嘿,我来帮你搞定这个Emoji文本框需求!

一、先说说你找到的这段代码

这段EmojiTextField子类能满足自动唤起并锁定Emoji键盘的核心需求,但有个小缺陷:它只管控了键盘的唤起和锁定,没限制输入内容——比如用户如果粘贴了非Emoji字符,文本框还是会接收。所以要完全实现“仅允许输入Emoji”的目标,得给它补充内容过滤的逻辑。

二、怎么在SwiftUI里用这个TextField?

SwiftUI没法直接使用UIKit的UITextField子类,得用UIViewRepresentable把它包装成SwiftUI能识别的组件,具体步骤如下:

1. 编写包装组件的代码

struct EmojiTextFieldView: UIViewRepresentable {
    @Binding var text: String
    var placeholder: String
    
    func makeUIView(context: Context) -> EmojiTextField {
        let textField = EmojiTextField()
        textField.placeholder = placeholder
        textField.delegate = context.coordinator
        // 这里可以自定义样式,比如字体大小、对齐方式
        textField.font = UIFont.systemFont(ofSize: 24)
        textField.textAlignment = .center
        return textField
    }
    
    func updateUIView(_ uiView: EmojiTextField, context: Context) {
        uiView.text = text
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    // 用Coordinator处理输入内容过滤
    class Coordinator: NSObject, UITextFieldDelegate {
        let parent: EmojiTextFieldView
        
        init(parent: EmojiTextFieldView) {
            self.parent = parent
        }
        
        // 拦截输入,只保留Emoji字符
        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            // 计算输入后的完整文本
            let newText = (textField.text as NSString?)?.replacingCharacters(in: range, with: string) ?? string
            // 过滤出仅包含Emoji的内容
            let emojiOnlyText = newText.filter { $0.isEmoji }
            // 更新绑定的文本值
            parent.text = emojiOnlyText
            // 返回false,因为我们已经手动处理了文本更新
            return false
        }
    }
}

// 给Character扩展一个判断是否为Emoji的方法
extension Character {
    var isEmoji: Bool {
        let scalarValue = String(self).unicodeScalars.first!.value
        // 覆盖常见的Emoji Unicode范围
        switch scalarValue {
        case 0x1F600...0x1F64F, 0x1F300...0x1F5FF, 0x1F680...0x1F6FF,
             0x1F1E0...0x1F1FF, 0x2600...0x26FF, 0x2700...0x27BF,
             0xFE00...0xFE0F, 0x1F900...0x1F9FF, 0x1F004...0x1F0CF:
            return true
        default:
            return false
        }
    }
}

2. 在你的SwiftUI视图中使用该组件

struct ContentView: View {
    @State private var emojiText = ""
    
    var body: some View {
        VStack(spacing: 20) {
            EmojiTextFieldView(text: $emojiText, placeholder: "来输入Emoji呀~")
                .padding()
                .border(Color.gray)
            
            Text("你输入的Emoji:\(emojiText)")
                .font(.title)
        }
        .padding()
    }
}

三、有没有更原生的SwiftUI方案?

如果你不想折腾UIKit子类,也可以用SwiftUI原生的TextField实现,代码更简洁:

struct EmojiOnlyTextField: View {
    @Binding var text: String
    var placeholder: String
    
    var body: some View {
        TextField(placeholder, text: $text)
            .keyboardType(.emoji) // 唤起Emoji键盘
            .onChange(of: text) { newValue in
                // 实时过滤,只保留Emoji
                text = newValue.filter { $0.isEmoji }
            }
            .padding()
            .border(Color.gray)
    }
}

不过这个方案有个小缺点:用户可以手动切换到其他键盘(比如英文键盘),而之前的UITextField子类方案会强制锁定Emoji键盘,用户无法切换。如果你的需求是必须只能使用Emoji键盘,那还是优先选择第一种方案哦~


内容的提问来源于stack exchange,提问作者Иван Покасов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 11:24:15