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

词形还原在物理设备正常,Xcode预览/模拟器/测试环境异常

SwiftUI NaturalLanguage词形还原在模拟器/Xcode预览中失效问题解决

问题概述

基于SwiftUI和NaturalLanguage框架编写的词形还原代码,在Mac、iOS 16.4/17.3物理设备上可正常运行,但在Xcode预览、模拟器及测试环境中无法生效。输入字符串"Pumpkins grow slow. Cars are fast."时,预期输出为"pumpkin grow slow. car be fast.",但模拟器返回未修改的原字符串,当前使用最新版Xcode和Sonoma系统。

原代码如下:

import SwiftUI
import NaturalLanguage

struct ContentView: View {
    var body: some View {
        VStack {
            Text(lemmatize())
        }
    }
  
  func lemmatize() -> String {
    let text = "Pumpkins grow slow. Cars are fast."
    
    let tagger = NLTagger(tagSchemes: [.lemma])
    tagger.string = text

    print (tagger.tagSchemes)

    var lemmaText: String = ""
    
    tagger.enumerateTags(in: text.startIndex..<text.endIndex, unit: .word, scheme: .lemma) { tag, range in
      let stemForm = tag?.rawValue ?? String(text[range])
      lemmaText += stemForm
      return true
    }
    
    return lemmaText
  }
}

原因分析

  1. 模拟器语言模型缺失:NaturalLanguage框架的词形还原依赖对应语言的预训练模型,模拟器默认可能未预装完整的英语语言模型,导致NLTagger无法正确提取lemma标签。
  2. 语言自动识别失败:未手动指定语言时,NLTagger可能无法自动识别文本语言,进而无法加载对应模型。
  3. 文本拼接逻辑缺陷:原代码仅拼接单词的词形还原结果,丢失了原文本中的空格、标点等非单词字符,即使真机运行正常,输出格式也不符合预期。

解决方案

1. 强制指定语言模型

在初始化NLTagger后,手动设置目标语言为英语,确保加载正确的词形还原模型:

tagger.setLanguage(.english, range: text.startIndex..<text.endIndex)

2. 修复文本拼接逻辑

保留原文本中的空格、标点等非单词内容,避免输出文本丢失格式:

  • 记录当前处理索引,在枚举单词时,先添加当前索引到单词范围之间的非单词内容
  • 枚举结束后,添加剩余的非单词内容

3. 优化枚举选项

使用.omitWhitespace和.omitPunctuation选项跳过空格和标点的枚举,专注处理单词单元。

修改后的完整代码

import SwiftUI
import NaturalLanguage

struct ContentView: View {
    var body: some View {
        VStack {
            Text(lemmatize())
        }
    }
  
    func lemmatize() -> String {
        let text = "Pumpkins grow slow. Cars are fast."
        
        let tagger = NLTagger(tagSchemes: [.lemma])
        tagger.string = text
        // 强制指定英语语言模型
        tagger.setLanguage(.english, range: text.startIndex..<text.endIndex)

        var lemmaText: String = ""
        var currentIndex = text.startIndex
        
        // 枚举单词,跳过空格和标点
        tagger.enumerateTags(in: text.startIndex..<text.endIndex, 
                             unit: .word, 
                             scheme: .lemma, 
                             options: [.omitWhitespace, .omitPunctuation]) { tag, range in
            // 添加单词前的非单词内容(空格、标点)
            if currentIndex < range.lowerBound {
                lemmaText += String(text[currentIndex..<range.lowerBound])
            }
            // 获取词形还原结果, fallback 到原词
            let stemForm = tag?.rawValue ?? String(text[range])
            lemmaText += stemForm
            currentIndex = range.upperBound
            return true
        }
        // 添加剩余的非单词内容
        if currentIndex < text.endIndex {
            lemmaText += String(text[currentIndex..<text.endIndex])
        }
        
        return lemmaText
    }
}

验证效果

修改后在模拟器、Xcode预览及测试环境中运行,输入"Pumpkins grow slow. Cars are fast."将输出预期结果:"pumpkin grow slow. car be fast."

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 19:37:19