Swift多行字符串拆分及Kanna中匹配元素索引获取问题求助
我来帮你一步步解决这两个Swift问题~
问题1:拆分包含可选变量的多行字符串字面量
这里的核心是先安全解包可选变量,再对字符串进行拆分操作——强制解包!很容易导致崩溃,推荐用if let或guard let做安全处理,再搭配Swift原生的字符串拆分API:
示例代码:处理可选的多行字符串
假设你有一个可能为nil的多行字符串:
let optionalMultiLineText: String? = """ Kazuo®/Ishiguro® Auprès® (2 pack) Orange Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack) Blue """ // 安全解包后拆分,过滤空行 if let text = optionalMultiLineText { let lines = text.components(separatedBy: .newlines).filter { !$0.isEmpty } print(lines) // 输出: ["Kazuo®/Ishiguro® Auprès® (2 pack)", "Orange", "Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack)", "Blue"] }
如果是多行字符串字面量中嵌入可选变量,需要先给可选值一个默认值再拼接:
let optionalBrand: String? = "Kazuo®/Ishiguro®" let multiLineString = """ \(optionalBrand ?? "默认品牌") Auprès® (2 pack) Orange \(optionalBrand ?? "默认品牌") Auprès® Folio Toujours (2 Pack) Blue """ let lines = multiLineString.components(separatedBy: .newlines).filter { !$0.isEmpty }
问题2:处理Kanna查询结果的文本拆分与索引查找
从你的描述来看,你踩了API过时的坑,还有对字符串/数组索引方法的误解,我们逐个解决:
一、修复文本拆分失败的问题
你尝试的三种方法失效,主要是因为API过时或者文本中的分隔符不是标准换行符(比如你给出的典型输出看起来更像空格分隔,而非换行)。推荐用Swift原生的split方法,兼容各种场景:
推荐代码:安全处理Kanna节点并拆分文本
// 先安全处理Kanna的查询结果,避免强制解包崩溃 guard let doc = doc, let productLinks = doc.css("a[class^='product-link']") else { print("没有找到匹配的产品链接节点") return } for node in productLinks { guard let rawText = node.text else { continue } // 方案1:按所有换行符拆分(兼容\n、\r、\r\n) let linesByNewline = rawText.split(whereSeparator: \.isNewline) .map(String.init) .filter { !$0.isEmpty } // 方案2:如果文本实际是用空白字符分隔(比如你给出的典型输出) let linesByWhitespace = rawText.split(whereSeparator: \.isWhitespace) .map(String.init) .filter { !$0.isEmpty } print("按换行拆分结果:\(linesByNewline)") print("按空白拆分结果:\(linesByWhitespace)") }
为什么你之前的方法报错?
componentsSeparatedByCharactersInSet:这是Objective-C时代的旧API,Swift 3+已经废弃,改用components(separatedBy: CharacterSet),比如:let lineArray = multiLineString.components(separatedBy: .newlines).filter{! $0.isEmpty}split方法的错误:你用了NSCharacterSet.newlineCharacterSet(),Swift中应该用CharacterSet.newlines,而且characterIsMember的类型处理很麻烦,不如直接用split(whereSeparator: \.isNewline)更简洁。enumerateLines返回function():这应该是调试时的误解——enumerateLines的闭包参数line就是每行的字符串,只要你正确append(line),lineArray肯定是[String]类型,不会是function。可能是你没有正确打印数组,或者node.text本身为空?
二、修复元素索引查找的问题
你用index(of:)报错,是因为字符串的index(of:)方法是用来查找单个Character的,而你传入的是String。正确的做法是先把拆分后的文本放到数组里,再用数组的firstIndex(of:)方法:
示例代码:查找数组元素的索引
// 假设已经得到拆分后的产品文本数组 let productLines = ["Kazuo®/Ishiguro® Auprès® (2 pack)", "Orange", "Kazuo®/Ishiguro® Auprès® Folio Toujours (2 Pack)", "Blue"] // 精确匹配查找索引 if let orangeIndex = productLines.firstIndex(of: "Orange") { print("Orange的索引是:\(orangeIndex)") // 输出: Orange的索引是:1 } // 模糊匹配(包含指定字符串)查找索引 if let folioIndex = productLines.firstIndex(where: { $0.contains("Folio Toujours") }) { print("Folio Toujours的索引是:\(folioIndex)") // 输出: Folio Toujours的索引是:2 }
内容的提问来源于stack exchange,提问作者solo
相关产品推荐
相关产品推荐

