2017-01-19 1 views
0

Пересмотр старого кода. Однажды я начал изучать, как работает код при разработке приложений для iOS, поэтому я приношу свои извинения за божественный viewController. Проблема при запуске приложения заключается в том, что после того, как пользователь начнет прокручивать табличное представление, метки начинают дублироваться друг над другом, и я уверен, что веб-просмотры, скорее всего, будут укладываться в стек. Я попытался изменить код, где я добавляю subviews в ячейку, используя метод cell.contentview.addsubview(), но это не изменяет поведение стекирования при прокрутке. Я также использую метод dequeueReusableCellWithIdentifier(), который, как я думал, очищает ячейки вместе, когда он выходит из экрана.Многоразовый UITableViewCell, дублирующий на свитке в Swift

Любая помощь здесь будет принята с благодарностью, поскольку я все еще участвую. Заранее спасибо.

Sample Screenshot

import UIKit 

class VimeoFeedViewController: UIViewController, NSXMLParserDelegate, UITableViewDataSource, UIWebViewDelegate, UITableViewDelegate 
{ 

    @IBOutlet var tbData: UITableView? 

    var parser = NSXMLParser() 
    var posts = NSMutableArray() 
    var elements = NSMutableDictionary() 
    var element = NSString() 
    var title1 = NSMutableString() 
    var date = NSMutableString() 
    var link = NSMutableString() 
    var webView = UIWebView() 
    var boxView = UIView() 
    var selectedCell = NSIndexPath() 
    var valueToPass:String! 
    var viewToPass: UIView! 
    var customWebView = UIWebView() 
    var url = NSURL() 





    //custom code for webviews to show up 
    var postTitle: String = String() 
    var postLink: String = String() 
    var ename: String = String() 
    //end of custom code for webviews to show up 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.beginParsing() 
     self.tbData?.backgroundColor = UIColor(patternImage: UIImage(named: "home-page-background.png")!) 
     webView.delegate = self 

    } 


    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    func beginParsing() 
    { 
     posts = [] 
     parser = NSXMLParser(contentsOfURL:(NSURL(string:"https://vimeo.com/channels/1000464/videos/rss"))!)! 
     parser.delegate = self 
     parser.parse() 
     tbData!.reloadData() 

    } 

    //XMLParser Methods 

    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) 
    { 
     element = elementName 
     if (elementName as NSString).isEqualToString("item") 
     { 
      elements = NSMutableDictionary() 
      elements = [:] 
      title1 = NSMutableString() 
      title1 = "" 
      date = NSMutableString() 
      date = "" 
      link = NSMutableString() 
      link = "" 
      postTitle = String() 
      postLink = String() 

     } 
    } 

    func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) 
    { 
     if (elementName as NSString).isEqualToString("item") { 
      if !title1.isEqual(nil) { 
       elements.setObject(title1, forKey: "title") 
      } 
      if !date.isEqual(nil) { 
       elements.setObject(date, forKey: "date") 
      } 
      if !link.isEqual(nil) { 
       elements.setObject(link, forKey: "link") 
      } 

      posts.addObject(elements) 
     } 
    } 

    func parser(parser: NSXMLParser, foundCharacters string: String) 
    { 
     if element.isEqualToString("title") { 
      title1.appendString(string) 
     } 
     if element.isEqualToString("pubDate") { 
      date.appendString(string) 
     } 
     if element.isEqualToString("link") { 
      link.appendString(string) 
     } 
    } 

    //Tableview Methods 
    func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
     return 1 
    } 

    func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 
     return 100.0 
    } 

    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 
     let headerView = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, 40)) 
     let imageName = "broughtToYouAG.png" 
     let image = UIImage(named: imageName) 
     let imageView = UIImageView(image: image!) 
     imageView.frame = CGRect(x: 0, y: 0, width: 420, height: 91) 
     headerView.addSubview(imageView) 
     headerView.backgroundColor = UIColor(patternImage: UIImage(named: "home-page-background.png")!) 
     return headerView 
    } 


    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ 
     return posts.count 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{ 

     var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell")! 
     if(cell.isEqual(NSNull)) { 
      cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)![0] as! UITableViewCell; 
     } 
     //start of customization 
     let textLabelCustom = UILabel(frame: CGRectMake(20, 0, 200, 91)) 
     let detailTextLabelCustom = UILabel(frame: CGRectMake(20, 0, 200, 20)) 
     let customWebView:UIWebView = UIWebView(frame: CGRectMake(245, 5, 149, 80)) 

     let url: NSURL? = NSURL(string: posts.objectAtIndex(indexPath.row).valueForKey("link") as! NSString as String) 



     let request: NSURLRequest = NSURLRequest(URL: url!) 
     customWebView.loadRequest(request) 
     customWebView.delegate = self 
     customWebView.scalesPageToFit = true 



     cell.contentView.addSubview(customWebView) 
     cell.contentView.addSubview(boxView) 
     //cell.addSubview(customWebView) 
     //cell.addSubview(boxView) 



     textLabelCustom.text = posts.objectAtIndex(indexPath.row).valueForKey("title") as! NSString as String 

     textLabelCustom.numberOfLines = 4 
     detailTextLabelCustom.numberOfLines = 2 
     textLabelCustom.textColor = UIColor.blackColor() 
     detailTextLabelCustom.font = UIFont(name: "AmericanTypewriter", size: 15) 
     textLabelCustom.font = UIFont(name: "HelveticaNeue", size: 18) 
     //cell.addSubview(textLabelCustom) 
     cell.contentView.addSubview(textLabelCustom) 
     //cell.addSubview(detailTextLabelCustom) 
     cell.contentView.addSubview(detailTextLabelCustom) 
     cell.backgroundColor = UIColor(patternImage: UIImage(named: "home-page-background.png")!) 
     let backgroundView = UIView() 
     backgroundView.backgroundColor = UIColor(patternImage: UIImage(named: "tableselectedimage.png")!) 
     cell.selectedBackgroundView = backgroundView 
     return cell as UITableViewCell 
    } 

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
     print("You selected cell #\(indexPath.row)!") 
     let indexPath = tbData!.indexPathForSelectedRow; 
     let url: NSURL? = NSURL(string: posts.objectAtIndex(indexPath!.row).valueForKey("link") as! NSString as String) 
     print("Video url selected: \(url)!") 

    } 


    override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!) { 
     if (segue.identifier == "vimeoWebSegue") { 
      //get a reference to the destination view controller 
      let destinationVC: playingThatVideoViewController = segue.destinationViewController as! playingThatVideoViewController 

      let indexPath = tbData!.indexPathForSelectedRow; 

      let url: NSURL? = NSURL(string: posts.objectAtIndex(indexPath!.row).valueForKey("link") as! NSString as String) 

      let titlegoing = posts.objectAtIndex(indexPath!.row).valueForKey("title") as! NSString as String 

      //set properties on the destination view controller 
      destinationVC.videoWebView = customWebView 
      destinationVC.urlbrought = url! 
      destinationVC.titlebrought = titlegoing 

     } 
    } 
} 

ответ

3

Вы должны создать пользовательские UITableViewCell с желаемыми видами (в вашем случае 2 UILabels и UIWebView), загрузите эту ячейку с пером в cellForRowAtIndexPath и заданных значений необходимо из массивов в indexPath.row соответствующим образом. Не создавайте и не добавляйте представления в cellForRowAtIndexPath, просто устанавливайте значения.

+0

Это звучит довольно просто и попробует следующее. Спасибо –

+1

Это лучший ответ, чем добавление просмотров в 'cellForRowAtIndexPath', а затем либо удаление, либо повторное добавление их при переработке, либо сообщение, если вы уже добавили их. Настройте прототип ячеек в вашей раскадровке, пометьте его желаемым идентификатором и дайте этому пользовательскому подклассу выходов UITableViewCell для ваших пользовательских представлений. Затем просто переместите ячейку на правильный тип и обратитесь к выходам ячеек. –

+0

Этот подход подходит только тогда, когда у вас есть статическое количество просмотров в ячейке. Что делать, если количество просмотров в ячейке динамическое? В этом случае вы должны добавлять представления программно, как @HandheldArchitect в вопросе. Итак, снова обращаясь к вопросу, я столкнулся с той же проблемой, что и множественные представления в ячейке несколько раз. Есть ли решение этой проблемы? –

1

В cellForRowAtIndexPath, так как клетки для повторного использования (отсюда и название метода «reusableCell»), вы должны удалить все подвидов клеточные, прежде чем добавить больше подвидов в клетку.

for subview in cell.contentView.subviews { 
    subview.contentView.removeFromSuperview() 
} 
+0

Как удалить подвидов, прежде чем они повторно? –

+0

Я добавил править – TheAmateurProgrammer

+0

Неправильная практика программирования, Вы никогда не должны удалять subView ячейки даже в методе 'didEndDisplayingCell'. Вместо этого используйте 'cell.contentView.removeAllSubviews()' in 'didEndDisplayingCell' –

1

Я использую метод dequeueReusableCellWithIdentifier(), а также которые я думал, что очищает клетки все вместе, как только он выходит за пределы экрана

Это не очищает клетки.

Он повторно использует ячейки, которые выходят из экрана, чтобы отображать ячейки, которые появляются на экране. Вы должны удалить фрагменты, прежде чем добавлять их снова. Одним из способов достижения этой цели будет установка тега для представления (view.tag = 10), а при деинкретировании ячейки вы будете делать cell.contentView.viewWithTag(10)?.removeFromSuperview().

+0

Когда вы говорите« перед добавлением их снова ».... Я не совсем уверен, что вы подразумеваете под этим, потому что я только вызвал метод addSubview один раз для каждой части контента. Как идти об очистке ячейки? tableView.reloadData() ??? –

1

Как другие ответы позволяют предположить, что вы удаляете и повторно добавляете представления. Id скорее предложит вам добавить их один раз и повторно использовать представления. Подкласс вашей ячейки и добавьте subviews один раз. Затем используйте prepareForReuse, чтобы очистить текст label.text = nil, например.

По соображениям производительности вы должны только сбросить атрибуты ячейки, которые не связаны с контентом, например, альфа, редактирование и состояние выбора.

+0

Большое спасибо, я видел метод prepareForReuse в документации UITableViews, но я не уверен, что ему нужно будет зайти в viewdidload или самостоятельно стоять в качестве своей собственной функции, а tableViewController вызовет метод автоматически? Надеюсь, что я только что сказал, имеет смысл, если я не извиняюсь. –

+1

@TheAtlantaGoat Метод viewDidLoad принадлежит ViewController, вам нужно создать подкласс UITableViewCell, который вызывает вызов метода. Я не кодируюсь быстро, но не могу показать вам пример, но вот хороший учебник, который я нашел для вас, который показывает вам, как подклассифицировать tableviewCell и правильно использовать его в виде таблицы. https://www.youtube.com/watch?v=adP2dG_C1XU, в основном идея заключается в том, что вы создаете выход/свойство ONCE и просто меняете его содержимое/текст/изображение при повторном использовании ячеек. –

1

Существует два возможных причины этой ошибки.

Причина 1

в методе cellForRowAtIndexPath вы создаете две метки на одной и той же позиции, которая перекрывает один на другой.

//Here is your code 
//Check the x-axis and y-axis of both textLabelCustom and detailTextLabelCustom are same. 
//It means both label will place on same axis but with different heights. 
let textLabelCustom = UILabel(frame: CGRectMake(20, 0, 200, 91)) 
let detailTextLabelCustom = UILabel(frame: CGRectMake(20, 0, 200, 20)) 
let customWebView:UIWebView = UIWebView(frame: CGRectMake(245, 5, 149, 80)) 

Измените это следующим образом. И увеличьте размер ячейки.

let textLabelCustom = UILabel(frame: CGRectMake(20, 0, 200, 90)) 
let detailTextLabelCustom = UILabel(frame: CGRectMake(20, 90, 200, 20)) 
let customWebView:UIWebView = UIWebView(frame: CGRectMake(245, 5, 149, 80)) 

Причина 2

Реализовать другой метод делегата didEndDisplayingCell и писать ниже линии

cell.contentView.removeAllSubviews() 
+0

Как небрежно, спасибо, что указали это. Это смущает, поэтому я очень ценю ваш опыт, чтобы начать движение в правильном направлении. –

 Смежные вопросы

  • Нет связанных вопросов^_^