UITableViewCell嵌入Firework iOS SDK的videoFeedController出现警告与视图消失问题
问题原因
你遇到的两个问题根因都来自子控制器添加流程不完整,以及UITableViewCell复用场景下的实例管理不当:
- 缺少UIKit要求的子控制器添加收尾方法
didMove(toParent:),导致videoFeedViewController未被正确关联到控制器层级,UIKit判定它是detached状态,触发警告; - 没有缓存
videoFeedViewController实例,且未处理cell复用逻辑,Firework SDK内部关闭播放视图时,会将未正确关联父控制器的自身视图从父视图移除,同时cell复用后旧实例被释放,导致视图消失。
解决方案
1. 补全子控制器添加/移除流程
UIKit对子控制器的容器化操作有严格的流程要求,必须完整调用对应方法:
添加流程:
- 父控制器调用
addChild(_:)传入子控制器 - 将子控制器的view添加到父视图
- 配置子view的约束/frame
- 子控制器调用
didMove(toParent:)传入父控制器
移除流程(用于cell复用时清理旧视图):
- 子控制器调用
willMove(toParent: nil) - 子控制器的view从父视图移除
- 子控制器调用
removeFromParent()
2. 缓存videoFeedViewController实例
在你的feedVC中新增缓存属性,避免每次cellForRow都创建新的实例,也防止实例被意外释放:
private var videoFeedCache: [IndexPath: VideoFeedViewController] = [:]
3. 修正后的cellForRow实现示例
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellID", for: indexPath) // 先清理cell上旧的子控制器,避免复用冲突 cell.contentView.subviews.forEach { subview in if let parentVC = subview.next as? VideoFeedViewController { parentVC.willMove(toParent: nil) subview.removeFromSuperview() parentVC.removeFromParent() } } // 从缓存取或者创建新的实例 let videoVC: VideoFeedViewController if let cached = videoFeedCache[indexPath] { videoVC = cached } else { videoVC = VideoFeedViewController() // 替换为你的Firework SDK初始化逻辑 videoFeedCache[indexPath] = videoVC } // 完整添加子控制器流程 self.feedVC?.addChild(videoVC) cell.contentView.addSubview(videoVC.view) videoVC.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ videoVC.view.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor), videoVC.view.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor), videoVC.view.topAnchor.constraint(equalTo: cell.contentView.topAnchor), videoVC.view.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor) ]) // 补全缺失的收尾调用 videoVC.didMove(toParent: self.feedVC) return cell }
额外注意
如果你的UITableView有大量cell,缓存太多VideoFeedViewController实例会占用过高内存,可以在tableView(_:didEndDisplaying:forRowAt:)方法里清理不可见区域的缓存,避免内存浪费。
内容的提问来源于stack exchange,提问作者As If Prince
相关产品推荐
相关产品推荐

