ios - 如何在 iOS RSS 应用程序中显示解析后的 XML 中的图像?

标签 ios swift xml xml-parsing rss

我有一个使用 Swift 编写的 iOS 应用程序,它可以从我网站的 RSS 提要中解析 XML。

我希望能够显示帖子的图像并显示相关内容(目前它只显示 XML 代码)。

以下是解析器及其控制的单元格的代码:

解析器:

import Foundation

struct RSSItem {
    var title: String
    var description: String
    var pubDate: String
}

// download xml from a server
// parse xml to foundation objects
// call back

class FeedParser: NSObject, XMLParserDelegate
{
    private var rssItems: [RSSItem] = []
    private var currentElement = ""

    private var currentTitle: String = "" {
        didSet {
            currentTitle = currentTitle.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    }
    private var currentDescription: String = "" {
        didSet {
            currentDescription = currentDescription.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    }
    private var currentPubDate: String = "" {
        didSet {
            currentPubDate = currentPubDate.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    }
    private var parserCompletionHandler: (([RSSItem]) -> Void)?

    func parseFeed(url: String, completionHandler: (([RSSItem]) -> Void)?)
    {
        self.parserCompletionHandler = completionHandler

        let request = URLRequest(url: URL(string: url)!)
        let urlSession = URLSession.shared
        let task = urlSession.dataTask(with: request) { (data, response, error) in
            guard let data = data else {
                if let error = error {
                    print(error.localizedDescription)
                }

                return
            }

            /// parse our xml data
            let parser = XMLParser(data: data)
            parser.delegate = self
            parser.parse()
        }

        task.resume()
    }

    // MARK: - XML Parser Delegate

    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:])
    {
        currentElement = elementName
        if currentElement == "item" {
            currentTitle = ""
            currentDescription = ""
            currentPubDate = ""
        }
    }

    func parser(_ parser: XMLParser, foundCharacters string: String)
    {
        switch currentElement {
        case "title": currentTitle += string
        case "description" : currentDescription += string
        case "pubDate" : currentPubDate += string
        default: break
        }
    }

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?)
    {
        if elementName == "item" {
            let rssItem = RSSItem(title: currentTitle, description: currentDescription, pubDate: currentPubDate)
            self.rssItems.append(rssItem)
        }
    }

    func parserDidEndDocument(_ parser: XMLParser) {
        parserCompletionHandler?(rssItems)
    }

    func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error)
    {
        print(parseError.localizedDescription)
    }

}

单元格 View Controller :

import UIKit

class NewsTableViewController: UITableViewController
{
    private var rssItems: [RSSItem]?
    private var cellStates: [CellState]?

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.estimatedRowHeight = 155.0
        tableView.rowHeight = UITableView.automaticDimension

        fetchData()
    }

    private func fetchData()
    {
        let feedParser = FeedParser()
        feedParser.parseFeed(url: "https://appleosophy.com/feed") { (rssItems) in
            self.rssItems = rssItems
            self.cellStates = Array(repeating: .collapsed, count: rssItems.count)

            OperationQueue.main.addOperation {
                self.tableView.reloadSections(IndexSet(integer: 0), with: .left)
            }
        }
    }


    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // Return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        guard let rssItems = rssItems else {
            return 0
        }

        // rssItems
        return rssItems.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! NewsTableViewCell
        if let item = rssItems?[indexPath.item] {
            cell.item = item
            cell.selectionStyle = .none

            if let cellStates = cellStates {
                cell.descriptionLabel.numberOfLines = (cellStates[indexPath.row] == .expanded) ? 0 : 4
            }
        }

        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    {
        tableView.deselectRow(at: indexPath, animated: true)
        let cell = tableView.cellForRow(at: indexPath) as! NewsTableViewCell

        tableView.beginUpdates()
        cell.descriptionLabel.numberOfLines = (cell.descriptionLabel.numberOfLines == 0) ? 3 : 0

        cellStates?[indexPath.row] = (cell.descriptionLabel.numberOfLines == 0) ? .expanded : .collapsed

        tableView.endUpdates()
    }

}

我的目标是在我的应用程序中拥有一个完全原生的 RSS 提要,该提要可以显示我的文章以及图像和归因于该文章的文本。

最佳答案

这个答案已经很晚了,但我正在做一个类似的项目。我正在使用 SwiftUI 并设法加载远程 URL。希望我的解决方案对您有所帮助:

首先加载图像

import Combine
import Foundation
class ImageLoader: ObservableObject { 
    var dataPublisher = PassthroughSubject<Data, Never>() 
    var data = Data() { 
        didSet { 
            dataPublisher.send(data) 
        } 
     }
init(urlString:String) { 
        guard let url = URL(string: urlString) else { return } 
        let task = URLSession.shared.dataTask(with: url) { data, response, error in 
        guard let data = data else { return }         
        DispatchQueue.main.async { 
           self.data = data 
        } 
    } 
    task.resume() 
  }
}

然后创建一个 imageView:

import Combine
import SwiftUI
struct ImageView: View {
    @ObservedObject var imageLoader:ImageLoader
    @State var image:UIImage = UIImage()
init(withURL url:String) {
        imageLoader = ImageLoader(urlString:url)
    }
var body: some View {
    VStack { 
        Image(uiImage: image)
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width:100, height:100)
    }.onReceive(imageLoader.dataPublisher) { data in
        self.image = UIImage(data: data) ?? UIImage()
    }
  }
}
struct ImageView_Previews: PreviewProvider {
    static var previews: some View {
        ImageView(withURL: "")
    }
}

然后你可以使用你的ImageView来查看图像: ImageView(withURL: data.imageURL)

关于ios - 如何在 iOS RSS 应用程序中显示解析后的 XML 中的图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56011653/

相关文章:

swift - 我如何获得边界 UIImageView Swift

ios - 在不影响存储对象的情况下更改值 - Realm swift

ios - 如何实现CallKit : SwiftUI

objective-c - 一次触摸两个 uitextview 时崩溃

swift - 如何为每个象限创建一个末端为圆角的圆

xml - 基本的 AIML 响应?

ios - 即使不支持横向,也以横向模式显示 UIImage

ios - 解散时如何从模态视图 Controller 传回数据

jquery - 使用 jQuery 提取 XML 中的 CDATA 以用作 HTML 内容

c# - 计算 XML 中的特定 XML 节点