我在我的应用中使用了第三方RSS Feed解析器库。我有近15页在每个页面的tableviews中显示RSS feed。问题是除了RSS提要链接之外,所有视图控制器都具有相同的代码。我不知道如何以这样的方式减少代码,使得所有的tableview都可以正常工作,同时减少代码的重复性。
我正在使用的代码是:
import UIKit
class TopStoriesViewController: UIViewController, FeedParserDelegate, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var parser: FeedParser?
var entries: [FeedItem]?
var spinnerActivity: MBProgressHUD! = nil
override func viewDidLoad() {
super.viewDidLoad()
self.spinnerActivity = MBProgressHUD.showAdded(to: self.view, animated: true);
self.spinnerActivity.label.text = "Loading";
self.spinnerActivity.detailsLabel.text = "Please Wait!";
self.spinnerActivity.isUserInteractionEnabled = false;
entries = []
DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async(execute: { () -> Void in
self.parser = FeedParser(feedURL: topStoriesLink) // this is the link i need to change in all view controllers
self.parser?.delegate = self
self.parser?.parse()
})
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
// MARK: - FeedParserDelegate methods
func feedParser(_ parser: FeedParser, didParseChannel channel: FeedChannel) {
}
func feedParser(_ parser: FeedParser, didParseItem item: FeedItem) {
}
func feedParser(_ parser: FeedParser, successfullyParsedURL url: String) {
}
func feedParser(_ parser: FeedParser, parsingFailedReason reason: String) {
}
func feedParserParsingAborted(_ parser: FeedParser) {
}
// MARK: - Network methods
func loadImageSynchronouslyFromURLString(_ urlString: String) -> UIImage? {
}
}
请帮忙。我是Swift的新手。我使用的是Swift 3.0。我需要为每个tableview显示上面显示的所有方法才能正确填充。
答案 0 :(得分:2)
// create super viewcontroller and write all your common code in that viewcontroller
class ParentVC: UIViewController, FeedParserDelegate, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var parser: FeedParser?
var entries: [FeedItem]?
var spinnerActivity: MBProgressHUD! = nil
override func viewDidLoad() {
super.viewDidLoad()
self.spinnerActivity = MBProgressHUD.showAdded(to: self.view, animated: true);
self.spinnerActivity.label.text = "Loading";
self.spinnerActivity.detailsLabel.text = "Please Wait!";
self.spinnerActivity.isUserInteractionEnabled = false;
entries = []
DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async(execute: { () -> Void in
self.parser = FeedParser(feedURL: topStoriesLink) // This is the only thing changing in every view controller
self.parser?.delegate = self
self.parser?.parse()
})
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return entries?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "FeedItemCell", for: indexPath) as UITableViewCell
let item = entries![(indexPath as NSIndexPath).row]
// image
if let imageView = cell.viewWithTag(1) as? UIImageView {
if item.mainImage != nil {
imageView.image = item.mainImage
} else {
if item.imageURLsFromDescription == nil || item.imageURLsFromDescription?.count == 0 {
item.mainImage = UIImage(named: "roundedDefaultFeed")
imageView.image = item.mainImage
}
DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async(execute: { () -> Void in
for imageURLString in item.imageURLsFromDescription! {
if let image = self.loadImageSynchronouslyFromURLString(imageURLString) {
item.mainImage = image
DispatchQueue.main.async(execute: { () -> Void in
imageView.image = image
self.tableView.reloadRows(at: [indexPath], with: .automatic)
})
break;
}
}
})
}
}
// title
if let titleLabel = cell.viewWithTag(2) as? UILabel {
titleLabel.text = item.feedTitle ?? "Untitled feed"
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
if let item = entries?[(indexPath as NSIndexPath).row] {
let nextScene = storyboard?.instantiateViewController(withIdentifier: "NewsDetailViewController") as! NewsDetailViewController
nextScene.newsTitle = item.feedTitle ?? "Untitled feed"
nextScene.newsDate = item.feedPubDate
nextScene.newsImgLink = item.mainImage
nextScene.newsDetail = item.feedContentSnippet ?? item.feedContent?.stringByDecodingHTMLEntities() ?? ""
nextScene.navBarTitle = "Top Stories"
let url = item.feedLink ?? ""
nextScene.websiteURL = url
self.navigationController?.pushViewController(nextScene, animated: true)
}
}
// MARK: - FeedParserDelegate methods
func feedParser(_ parser: FeedParser, didParseChannel channel: FeedChannel) {
// Here you could react to the FeedParser identifying a feed channel.
DispatchQueue.main.async(execute: { () -> Void in
print("Feed parser did parse channel \(channel)")
})
}
func feedParser(_ parser: FeedParser, didParseItem item: FeedItem) {
DispatchQueue.main.async(execute: { () -> Void in
print("Feed parser did parse item \(item.feedTitle)")
self.entries?.append(item)
})
}
func feedParser(_ parser: FeedParser, successfullyParsedURL url: String) {
DispatchQueue.main.async(execute: { () -> Void in
if ((self.entries?.count)! > 0) {
print("All feeds parsed.")
self.spinnerActivity.hide(animated: true)
self.tableView.reloadData()
} else {
print("No feeds found at url \(url).")
self.spinnerActivity.hide(animated: true)
//show msg - no feeds found
}
})
}
func feedParser(_ parser: FeedParser, parsingFailedReason reason: String) {
DispatchQueue.main.async(execute: { () -> Void in
print("Feed parsed failed: \(reason)")
self.entries = []
self.spinnerActivity.hide(animated: true)
//show msg - feed parsing failed
})
}
func feedParserParsingAborted(_ parser: FeedParser) {
print("Feed parsing aborted by the user")
self.entries = []
self.spinnerActivity.hide(animated: true)
//show msg - feed parsing aborted
}
// MARK: - Network methods
func loadImageSynchronouslyFromURLString(_ urlString: String) -> UIImage? {
if let url = URL(string: urlString) {
let request = NSMutableURLRequest(url: url)
request.timeoutInterval = 30.0
var response: URLResponse?
let error: NSErrorPointer? = nil
var data: Data?
do {
data = try NSURLConnection.sendSynchronousRequest(request as URLRequest, returning: &response)
} catch let error1 as NSError {
error??.pointee = error1
data = nil
}
if (data != nil) {
return UIImage(data: data!)
}
}
return nil
}
}
//TopStoriesViewController.swift
// Use ParentVC instead of UIViewController
class TopStoriesViewController : ParentVC {
override func viewDidLoad() {
super.viewDidLoad()
}
}
//AnotherViewController.swift
// Use ParentVC instead of UIViewController
class AnotherViewController : ParentVC {
override func viewDidLoad() {
super.viewDidLoad()
}
}
答案 1 :(得分:2)
我建议:
创建一个名为UIViewController
的基类,名为-for example- BaseViewController
,并让所有具有相同代码的视图控制器(从RSS源链接除外)继承它;在其中添加所需的全部功能,默认情况下,所有子类应具有在基类中实现的相同功能。
要更改每个视图控制器的 url ,您应该在基本视图控制器中声明一个名为-for-example- url
的属性,并将其值更改为当前的视图控制器。请注意,这也应该适用于在子类中应具有不同值的任何属性。
为了可重用,您应该让具有该需求的任何对象将其datasource
/ delegate
设置为符合基类(例如:tableView.delegate = super.self()
)。
示例:强>
BaseViewController:
class BaseViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var url: String = "default url"
var cellIdentifier: String = "cell"
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("default implemntation")
}
}
TopStoriesViewController(子类):
class TopStoriesViewController: BaseViewController {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
url = "top stories url"
tableView.dataSource = super.self()
tableView.delegate = super.self()
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("a cell has been selected, custom implemntation")
}
}
请注意,该示例演示了实现此目的的逻辑,您需要以符合逻辑的方式实现其他功能。
希望这有帮助。