Sorry for the late reply.
A bit confused of how I'm supposed to use ArticlesParser in the ObservableObject. Here's the code so if I missed something, it's here:
class ArticlesInfo: ObservableObject {
@Published var articles: [Article] = []
func loadArticles() {
class ArticlesParser: XMLParser {
var dateTimeZone = TimeZone(abbreviation: "GMT-6")
lazy var dateFormater: DateFormatter = {
let df = DateFormatter()
df.locale = Locale(identifier: "en_US_POSIX")
df.dateFormat = "MMM dd, yyyy"
df.timeZone = dateTimeZone
return df
}()
private var textBuffer: String = ""
private var nextArticle: Article? = nil
override init(data: Data) {
super.init(data: data)
self.delegate = self // Cannot assign value of type 'ArticlesParser' to type 'XMLParserDelegate?'
}
}
extension ArticlesParser: XMLParserDelegate { // Declaration is only valid at file scope
// Called when opening tag (`elementName`) is found
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
switch elementName {
case "posts":
nextArticle = Article()
case "title":
textBuffer = ""
case "date":
textBuffer = ""
case "author":
textBuffer = ""
case "img":
textBuffer = ""
case "content":
textBuffer = ""
default:
print("Ignoring \(elementName)")
break
}
}
// Called when closing tag (`/elementName`) is found
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
switch elementName {
case "posts":
if let article = nextArticle {
articles.append(article) // Cannot find 'articles' in scope
}
case "title":
nextArticle?.title = textBuffer
case "date":
print("date: \(textBuffer)")
nextArticle?.date = dateFormater.date(from: textBuffer)
case "author":
nextArticle?.author = textBuffer
case "img":
print("img: \(textBuffer)")
nextArticle?.img = URL(string: textBuffer)
case "content":
nextArticle?.content = textBuffer
default:
print("Ignoring \(elementName)")
break
}
}
// Called when a character sequence is found
// This may be called multiple times in a single element
func parser(_ parser: XMLParser, foundCharacters string: String) {
textBuffer += string
}
// Called when a CDATA block is found
func parser(_ parser: XMLParser, foundCDATA CDATABlock: Data) {
guard let string = String(data: CDATABlock, encoding: .utf8) else {
print("CDATA contains non-textual data, ignored")
return
}
textBuffer += string
}
// For debugging
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print(parseError)
print("on:", parser.lineNumber, "at:", parser.columnNumber)
}
}
}
}