2017-09-12 4 views
0

Swift에서 XML 구문 분석을 처음 사용하고이 코드를 Parsing XML from URL in Swift에 발견했지만 코드를 실행하려고하면 EXC_BAD_INSTRUCTION 오류가 발생합니다. 에러의 설명을 읽 fatal error: unexpectedly found nil while unwrapping an Optional valueSwift에서 XML 구문 분석 4

이 내 간단한 XML 파일입니다

<xml> 
    <book> 
     <title>Book Title</title> 
     <author>Book Author</author> 
    </book> 
</xml> 

다음 코드는 XMLParser 객체를 만들고 내 문서에있는 XML 파일을 구문 분석합니다. currentDictionaryresults 사전에 추가 될 때

// a few constants that identify what element names we're looking for inside the XML 

let recordKey = "book" 
let dictionaryKeys = ["title","author"] 

// a few variables to hold the results as we parse the XML 

var results: [[String: String]]!   // the whole array of dictionaries 
var currentDictionary: [String: String]! // the current dictionary 
var currentValue: String?     // the current value for one of the keys in the dictionary 

// start element 
// 
// - If we're starting a "record" create the dictionary that will hold the results 
// - If we're starting one of our dictionary keys, initialize `currentValue` (otherwise leave `nil`) 


func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { 

    if elementName == recordKey { 

     currentDictionary = [String : String]() 

    } else if dictionaryKeys.contains(elementName) { 

     currentValue = String() 

    } 
} 

// found characters 
// 
// - If this is an element we care about, append those characters. 
// - If `currentValue` still `nil`, then do nothing. 

func parser(_ parser: XMLParser, foundCharacters string: String) { 

    currentValue? += string 

} 

// end element 
// 
// - If we're at the end of the whole dictionary, then save that dictionary in our array 
// - If we're at the end of an element that belongs in the dictionary, then save that value in the dictionary 


func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { 

    if elementName == recordKey { 

     results.append(currentDictionary) 
     currentDictionary = nil 

    } else if dictionaryKeys.contains(elementName) { 

     currentDictionary[elementName] = currentValue 
     currentValue = nil 

    } 
} 

// Just in case, if there's an error, report it. (We don't want to fly blind here.) 

func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) { 

    print(parseError) 

    currentValue = nil 
    currentDictionary = nil 
    results = nil 

} 

오류가 didEndElement 방법에서 찾을 수 있습니다 :

// get xml file path from Documents and parse 

let filePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last?.appendingPathComponent("example.xml") 

let parser = XMLParser(contentsOf: filePath!) 
parser?.delegate = self 

if (parser?.parse())! { 
    print(self.results) 
} 

여기 내 사전을 XMLParserDelegate 메소드를 구현하고 정의합니다.

func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { 

    if elementName == recordKey { 

     results.append(currentDictionary) // Line with Error 
     currentDictionary = nil 

    } else if dictionaryKeys.contains(elementName) { 

     currentDictionary[elementName] = currentValue 
     currentValue = nil 

    } 
} 

이 문제를 해결할 수 있도록 도와주세요. Parsing XML from URL in Swift에 제공된 정확한 코드를 사용하고있어 문제가없는 것 같습니다. 내가 뭐 잘못하고 있니?

답변

1

코드는 실제로 results을 초기화하지 않으므로 처음 사용하려고 시도 할 때 nil 선택적 값을 강제로 푸시하려고합니다. 그 나쁜. 암묵적으로 래핑되지 않은 옵션으로 선언 할 이유가 없습니다. 당신의 parser(_:parseErrorOccurred:) 방법에서

results = nil 

: 또한 줄을 제거해야합니다

var results = [[String: String]]() 

:

var results: [[String: String]]! 

에 :

당신은 변경해야합니다.

당신보다는 당신이 당신의 코드를 다음과 같이 변경 할 수 있습니다 results는 선택 사양 일 것이다 경우

변경 results의 선언 :

var results: [[String: String]]? = [[String: String]]() 

변경 :

results.append(currentDictionary) 

을 ~까지 :

results?.append(currentDictionary) 

그리고 results = nil 행은 parser(_:parseErrorOccurred:)에 두십시오.

+0

@ 롭 감사합니다. 초기의 대답은 더 큰 그림을 보지 않고 충돌의 원인에 더 집중했습니다. 귀하의 의견은 좋은 하나의 대답은 이제 두 가지 접근 방식을 반영합니다. – rmaddy

+0

나는 이것이 시작 문제라는 것을 알았고, 선택 사항없이 시도했지만 작동하지 않았다. 이것은 더 의미가 있습니다! 고마워요! @rob – user1526521

+0

@ user1526521 - 나는 rmaddy의 대답을 받아 들일 것을 제안합니다. [누군가 내 질문에 대답하면 어떻게해야합니까?] (https://stackoverflow.com/help/someone-answers)를 참조하십시오. – Rob

0

rmaddy가 문제를 올바르게 진단했습니다 (+1). results은 초기화되지 않았습니다.

나는 대부분 그대로 코드를 떠나 제안하지만, 단지 다음과 같이 results를 초기화합니다 parserDidStartDocument 방법을 추가합니다 :

func parserDidStartDocument(_ parser: XMLParser) { 
    results = [[:]] 
}