向 uitableviewcell 发送新值并重新渲染

Posted

技术标签:

【中文标题】向 uitableviewcell 发送新值并重新渲染【英文标题】:Send new value to uitableviewcell and re-render 【发布时间】:2020-07-02 20:07:18 【问题描述】:

我有 UITableView,默认情况下显示 2 个项目。当我将手机切换到横向模式时,我需要重新渲染所有 tableview 行,然后在行中显示 3 个项目。我已经有了渲染 2 或 3 个项目的逻辑以及我需要的行数,但我不知道如何传递 isLandscaped 布尔值,告诉单元格如何渲染(横向或纵向)。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    
    let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! BookshelfCell

    cell.changeOrientation(orientation: isLandscaped) // doesn't work
    cell.isLandscaped = self.isLandscaped // doesn't work
        
     if isLandscaped 
        
        cell.book1 = books[indexPath.row * 3] // Return for left side
        
        if (indexPath.row * 3 + 1) < books.count 
            cell.book2 = books[indexPath.row * 3 + 1] // Return for middle
        
        
        if (indexPath.row * 3 + 2) < books.count 
            cell.book3 = books[indexPath.row * 3 + 2] // Return for right side
        
        
     else  // portrait
        cell.book1 = books[indexPath.row * 2] // Return for left side
        
        if (indexPath.row * 2 + 1) < books.count 
            cell.book2 = books[indexPath.row * 2 + 1] // return for right side
        
    
    return cell

在 ViewController 中更改 isLandscaped book 的功能(工作正常):

@objc func rotated() 
    if UIDevice.current.orientation.isLandscape 
        isLandscaped = true
    
    if UIDevice.current.orientation.isPortrait 
        isLandscaped = false
    
    tableView.reloadData()

我尝试了协议委托模式,我再次能够从 VC 向单元格发送值,但无法使用 3 个项目重新渲染 tableview。我认为问题在于我总是将isLandscaped bool 发送到现有单元格,但我没有用新值渲染新单元格。如果我默认在单元格中设置 3 个项目(isLandscaped = true),它工作正常。也许有可能以某种方式初始化单元格?我还尝试在任何地方打电话给cell.reloadInputViews()tableview.reloadData()。也没什么。

我需要使用 uitableview,它应该可以在 ios 9.0 上运行,这是这个任务的规则。 如果有人有时间提供帮助,我将不胜感激。如果需要,我可以发送更多代码。

【问题讨论】:

【参考方案1】:

在 BookshelfCell 中创建一个函数来处理设置

func setupCell(WithBooks books: [Books], Row row: Int, IsLandscape isLandscape: Bool)

在此方法中包含您的 UI 代码

这样称呼

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    
    let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! BookshelfCell

    print("Setting up cell with. IsLandscape: \(self.isLandscaped)")
    cell.setupCell(WithBooks: books, Row: indexPath.row, IsLandscape: self.isLandscaped)
    
    return cell

一个简单的 .reloadData() 应该总是足够重新渲染单元格,无需直接单独说出它们。

检查您的 self.isLandscape 是否始终正确,将其打印到 cellForRow 中的控制台

【讨论】:

我理解你的逻辑并且它有效,但是 .reloadData() 只是没有做任何事情。如果我以横向模式打开应用程序 - 它会显示 3 本书。如果是纵向 - 2 本书。但是每当我改变手机的模式/方向并在 tableview 上调用 reloadData - 它永远不会改变。【参考方案2】:

您可以尝试在视图控制器中使用viewWillTransition(to:with:) 方法。每次视图大小发生变化时,它都会调用此方法,以便检测方向变化。所以在你的情况下,你可以在那里调用 reloadData 方法。

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
        super.viewWillTransition(to: size, with: coordinator)
        if UIDevice.current.orientation.isLandscape 
            // Logic for landscape
         else 
            // Logic for portrait
        
    

编辑: 当方向改变时,Apple 还会发送名为 orientationDidChangeNotification 的通知。所以你可以像这样使用通知中心:

override func viewDidLoad() 
    super.viewDidLoad()        

    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)


deinit 
   NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)         


func rotated() 
    if UIDevice.current.orientation.isLandscape 
        // Logic for landscape
     else 
        // Logic for portrait
    

【讨论】:

以上是关于向 uitableviewcell 发送新值并重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

R:如何使用其他列中的数据在一列中创建多个新值并为每个新值重复行?

如何获取新值并取消文本输入字段中的事件?

Unity 向 UI Slider 发送值并更新 Slider bar

UITableViewCell detailTextLabel 在分配新值时不会更新其文本

UITableViewCell detailTextLabel在为其分配新值时不会更新其文本

字符串