为啥我的代码可以在 Xcode Playground 中运行,但不能在我的项目中运行?

Posted

技术标签:

【中文标题】为啥我的代码可以在 Xcode Playground 中运行,但不能在我的项目中运行?【英文标题】:Why does my code work in Xcode Playground but not in my project?为什么我的代码可以在 Xcode Playground 中运行,但不能在我的项目中运行? 【发布时间】:2020-05-29 14:58:04 【问题描述】:

我正在尝试解析 Calibre 用于通过 Swift 管理电子书的 metadata.opf 文件。

我设法在操场上解析文档:


import Foundation

class Metadata: CustomStringConvertible 

    var uuid = ""
    var title = ""
    var creators = [""]
    var serie = ""
    var serieIndex = 0

    var description: String  return
        "UUID: \(uuid)\nTitre: \(title)\nAuteur(s): \(creators)\nSérie: Tome \(serieIndex) de la série \(serie)"
    



class OPFParser: NSObject 
    var xmlParser: XMLParser?
    var metadata: [Metadata] = []
    var xmlText = ""
    var currentMetadata: Metadata?
    var calibreAttributes: [String: String] = [:]
    var isUUID = false

    init(withXML xml: String) 
        if let data = xml.data(using: .utf8)
            xmlParser = XMLParser(data: data)
        
    

    func parse() -> [Metadata] 
        xmlParser?.delegate = self
        xmlParser?.parse()
        return metadata
    


extension OPFParser: XMLParserDelegate 
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) 
        xmlText = ""
        if elementName == "metadata" 
            currentMetadata = Metadata()
        
        if elementName == "meta" 
            //print("\(attributeDict["content"]) : \(attributeDict["name"])")
            if attributeDict["name"] == "calibre:series" 
                if let serie = attributeDict["content"] 
                    currentMetadata?.serie = serie
                
            
            if attributeDict["name"] == "calibre:series_index" 
                if let serieIndex = attributeDict["content"] 
                    currentMetadata?.serieIndex = Int(serieIndex) ?? 0
                
            
        
        if elementName == "dc:identifier" 
            if let uuuid = attributeDict["opf:scheme"]
                if uuuid == "uuid" 
                    isUUID = true
                 else  isUUID = false

            
        
    

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) 
        switch elementName 
        case "dc:identifier":
            if isUUID == true 
                currentMetadata?.uuid = xmlText.trimmingCharacters(in: .whitespacesAndNewlines)
            
        case "dc:title":
            currentMetadata?.title = xmlText.trimmingCharacters(in: .whitespacesAndNewlines)
        case "dc:creator":
            currentMetadata?.creators.append(xmlText.trimmingCharacters(in: .whitespacesAndNewlines))
        case "metadata":
            if let meta = currentMetadata 
                metadata.append(meta)
            
        default:
            break

    
    

    func parser(_ parser: XMLParser, foundCharacters string: String) 
        xmlText += string
    


class TestMetadata 
func metadataDisplay() 

    if let xmlUrl = Bundle.main.url(forResource: "metadata1", withExtension: "opf") 
        let xml = try! String(contentsOf: xmlUrl)
        let opfParser = OPFParser(withXML: xml)
        let bandeDessinees = opfParser.parse()
        for bandeDessinee in bandeDessinees 
            bandeDessinee.creators = bandeDessinee.creators.filter( $0 != "")
            print(bandeDessinee)
        
     else print("fichier non trouvé")




let testMetadata = TestMetadata()

testMetadata.metadataDisplay()

metadataDisplay 函数起作用,并打印格式化的元数据。不幸的是,当切换到我的项目时,metadataDisplay 不打印任何内容。 bandedessinees 数组为空。我使用的是相同的代码,只是我从 swiftUI 文件中的按钮调用 metadataDisplay。我尝试多次重构代码,修改了'init()function of myOPFParser`类,但不幸的是我无法弄清楚为什么我的元数据没有打印在控制台中。

感谢您的帮助, 艾曼。

示例 metadata.opf 文件:

<?xml version='1.0' encoding='utf-8'?>
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="uuid_id" version="2.0">
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
        <dc:identifier opf:scheme="calibre" id="calibre_id">143</dc:identifier>
        <dc:identifier opf:scheme="uuid" id="uuid_id">03badde9-0932-41ab-bd31-2dbba989a7f5</dc:identifier>
        <dc:title>Tome 1</dc:title>
        <dc:creator opf:file-as="Debeurme, Ludovic" opf:role="aut">Ludovic Debeurme</dc:creator>
        <dc:contributor opf:file-as="calibre" opf:role="bkp">calibre (4.15.0) [https://calibre-ebook.com]</dc:contributor>
        <dc:date>2018-05-20T16:16:27+00:00</dc:date>
        <dc:language>en</dc:language>
        <meta content="&quot;Ludovic Debeurme&quot;: &quot;&quot;" name="calibre:author_link_map"/>
        <meta content="Epiphania" name="calibre:series"/>
        <meta content="1" name="calibre:series_index"/>
        <meta content="2020-05-16T13:01:05.580464+00:00" name="calibre:timestamp"/>
        <meta content="Tome 1" name="calibre:title_sort"/>
        <meta name="calibre:user_metadata:#shelves" content="&quot;table&quot;: &quot;custom_column_1&quot;, &quot;is_editable&quot;: true, &quot;is_custom&quot;: true, &quot;rec_index&quot;: 22, &quot;is_category&quot;: true, &quot;is_multiple2&quot;: &quot;ui_to_list&quot;: &quot;,&quot;, &quot;list_to_ui&quot;: &quot;, &quot;, &quot;cache_to_list&quot;: &quot;|&quot;, &quot;name&quot;: &quot;Shelves&quot;, &quot;is_multiple&quot;: &quot;|&quot;, &quot;is_csp&quot;: false, &quot;category_sort&quot;: &quot;value&quot;, &quot;#extra#&quot;: null, &quot;kind&quot;: &quot;field&quot;, &quot;#value#&quot;: [], &quot;display&quot;: &quot;is_names&quot;: false, &quot;description&quot;: &quot;&quot;, &quot;search_terms&quot;: [&quot;#shelves&quot;], &quot;datatype&quot;: &quot;text&quot;, &quot;colnum&quot;: 1, &quot;label&quot;: &quot;shelves&quot;, &quot;link_column&quot;: &quot;value&quot;, &quot;column&quot;: &quot;value&quot;"/>
    </metadata>
    <guide>
        <reference href="cover.jpg" title="Cover" type="cover"/>
    </guide>
</package>

【问题讨论】:

您是否设置了断点并在调试中单步执行以查看发生了什么? xml 的值是多少?旁注:您应该将let xml = try String(contentsOf: xmlUrl) 包装在do catch 块中以确保String(contentsOf: xmlUrl) 成功。 我在 SwiftUI 视图中尝试了您的代码,没有遇到任何问题。 @DonMag 我已经使用打印语句来尝试查找问题,并为 xml 找到了一个值。感谢您的 do/catch 建议,我会将其添加到我的函数中! @Frankenstein 感谢您的反馈,我会换一个视图试试。 @AymaneBengrina - 你能发布一个示例文件看看我们是否可以复制这个问题吗? 【参考方案1】:

我终于弄对了,问题出在 XML 文件的编码上。通过从XMLParser(data: Data) 切换到XMLParser(contentsOf: URL),解析器返回一个非空数组。

【讨论】:

以上是关于为啥我的代码可以在 Xcode Playground 中运行,但不能在我的项目中运行?的主要内容,如果未能解决你的问题,请参考以下文章

xcode 快捷键

xcode 快捷键

为啥 Xcode 无法识别我的核心数据实体的属性

为啥 Xcode 将我的所有代码编译两次,导致任何全局变量的链接器错误?

为啥我的 GraphQL 订阅在本地服务器上运行,但在实时服务器上部署时却不行

为啥我的程序可以在 Xcode 中运行,但不能作为单独的应用程序运行?