2017-02-13 12 views
0

私のサードパーティのRSSフィードパーサライブラリを私のアプリケーションに使用しました。私は各ページのテーブルビューでRSSフィードを表示するほぼ15ページを持っています。問題は、すべてのビューコントローラがRSSフィードリンクを除いて同じコードを持つことです。私は、コードの重複を減らしながら、現在作業中のすべてのテーブルビューが機能するような方法でコードを減らす方法を知らない。すべてのビューコントローラでTableViewの繰り返しコード - Swift 3

私が使用しているコードは次のとおりです。

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を使用しています。各テーブルビューが適切に配置されるためには、上記のすべてのメソッドが必要です。

答えて

2

から私がすることをお勧め:

  • は例 - BaseViewController -forと呼ばれるタイプUIViewControllerの基本クラスを作成し、RSSを除いて同じコードを持つすべてのView Controllerを聞かせてフィードリンクを継承する。必要な機能をすべて追加してください。デフォルトでは、すべてのサブクラスは基本クラスで同じ機能が実装されていなければなりません。

  • 各ビューコントローラのURLを変更するためには、例 - url -forと呼ばれるベース・ビュー・コントローラ内のプロパティを宣言し、現在のビューコントローラのために所望される値を変更すべきです。これは、サブクラスで異なる値を持つべきプロパティにも適用する必要があることに注意してください。

  • 再利用のためには、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") 
    } 
} 

注、あなたは他のfeaを実装する必要がありますあなたにとって理にかなった方法でお試しください。

これが役に立った。

+0

BaseViewControllerからself.tableView.reloadData()のようなテーブルを再ロードするにはどうしたらいいですか?私はその行にあいまいなエラーメッセージを表示しています。 – Mamta

+0

この場合、次のオプションがあります。1テーブルビューをリロードするメソッドをオーバーライドします。 2-基本クラスの 'tableView'を宣言し、コンポーネントのIBOutletをスクリーンショットに示された@YogeshMakwanaとして接続します。 –

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() 

      } 

     } 
  • あなたparentVC @IBOutlet弱いのvarのtableView接続:のUITableViewを!ストーリーボード storyboard image
+0

ParentVCからself.tableView.reloadData()のようなテーブルを再ロードするにはどうすればよいですか?私はその行にあいまいなエラーメッセージを表示しています。 – Mamta

+1

self.tableView.reloadData()を使用するだけで、@IBOutletを作成することを忘れないでください。弱いvar tableView:UITableView! parentVCのみ –

+0

ParentVCでコンセントを作るにはどうしたらいいですか?私は15種類のテーブルビューを持っていますか?それらをすべて接続するには? – Mamta

関連する問題