Post

Replies

Boosts

Views

Activity

Reply to (Expansion) Retrieve articles from an XML parser
Sorry, I do not understand why you removed it. It is I who is confused. Apologies, I must have switched it around. ArticlesParser now holds articles as a published variable. But ArticlesInfo - where the loadArticles() function is held - now cannot call articles because that property does not exist in ArticlesInfo. class ArticlesInfo: ObservableObject {     var dataUrl = URL(string: https://storage.googleapis.com/thehairsociety/2021/03/2f23e2d4-ths.xml)     func loadArticles() {         do {             if FileManager.default.fileExists(atPath: dataUrl!.path) {                 return             }             //Read `Data` from a file specified by URL             let data = try Data(contentsOf: dataUrl!)             //Parse Available Articles             let articles = try // ArticlesParser? JSONDecoder?             self.articles = articles // -- Value of type 'ArticlesInfo' has no property 'articles'         } catch {             print(error)         }     } } So do I need to call articles from ArticlesParser or should I just redefine articles? Hopefully this clears some things up a bit. On the topic of using the Lunch Card method, would using JSON be easier to use than XML? I'm curious because after doing a few tests it seems it's a bit simpler though I haven't tested actually article content (HTML) yet.
Topic: App & System Services SubTopic: General Tags:
Mar ’21
Reply to (Expansion) Call a Class into views
You have no need to (and should not, in this case) make ArticlesParser a local class nested in a function. Good to know. I just need to know where to put this. I will make this a separate thread because this is pretty much the parser I needed. Edit: New thread: https://developer.apple.com/forums/thread/675586
Topic: App & System Services SubTopic: General Tags:
Mar ’21
Reply to (Expansion) Call a Class into views
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)             }         }     } }
Topic: App & System Services SubTopic: General Tags:
Mar ’21
Reply to (Expansion) Retrieve articles from an XML parser
Why did you remove articles? I completely do not understand why. I don't understand how I removed articles. Sorry if I'm missing something but I don't remember ever removing it. It's in the ObservableObject where you told me to put it in the first place. You can do it in the same way: class ArticlesInfo: ObservableObject { @Published var articles: ... //... func loadArticles() { // Use `ArticlesParser` here //... } }
Topic: App & System Services SubTopic: General Tags:
Mar ’21
Reply to (Expansion) Retrieve articles from an XML parser
extension ArticlesInfo { var dataUrl: URL { FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent("THS.xml") } func saveArticles() { do { //Convert Array of `CardInfo` to `Data` let data = try JSONEncoder().encode(dataUrl) //Write `Data` to a file specified by URL try data.write(to: dataUrl, options: .atomic) } catch { print(error) } } func loadArticles() { do { if FileManager.default.fileExists(atPath: dataUrl.path) { return } //Read `Data` from a file specified by URL let data = try Data(contentsOf: dataUrl) //Parse Available Articles let articles = try JSONDecoder().decode([ArticleInfo].self, from: data) self.articles = articles } catch { print(error) } } } The code that was here was moved into ArticlesInfo itself and eventually changed into what it is now.
Topic: App & System Services SubTopic: General Tags:
Mar ’21