Swift table 在 table 视图单元格中播放视频的视图,内存泄漏
Swift table view with videos playing in table view cells, memory leak
我正在制作一个 iOS 应用程序,可以将其与带有视频源(无图像)的 Instagram 进行比较。我有一个 table 显示自定义 table 视图单元格,每个 table 视图单元格包含一个使用 AVKit 播放的视频。我现在有 6 个单元格正在加载,它使用了令人难以置信的内存量来显示它们。像 facebook、instagram 或 vine 这样的应用程序如何在不使用大量内存的情况下显示这么多视频?
下面是我目前使用的代码。
var cells: [VideoCell] = []
var cellPostkeys: [String] = []
@IBOutlet weak var feedTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
feedTableView.delegate = self
feedTableView.dataSource = self
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 250
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videoURLs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let url = videoURLs[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "testcell") as? VideoCell {
if (cellPostkeys.contains(url)) {
let index = cellPostkeys.firstIndex(of: url)
cells[index!] = cell
} else {
cells.append(cell)
cellPostkeys.append(url)
}
cell.playvid(url: url)
return cell
} else {
return VideoCell()
}
}
}
这是我自定义 table 视图单元格的代码
class VideoCell: UITableViewCell {
@IBOutlet weak var videoView: UIView!
var player : AVPlayer!
var avPlayerLayer : AVPlayerLayer!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
override func layoutSubviews() {
super.layoutSubviews()
//
}
func stopvid() {
self.player = nil
self.avPlayerLayer = nil
}
func playvid(url: String) {
self.player = AVPlayer(url: URL(string: url)!)
self.avPlayerLayer = AVPlayerLayer(player: self.player)
self.avPlayerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
self.player.automaticallyWaitsToMinimizeStalling = false
avPlayerLayer.frame = videoView.layer.bounds;
self.videoView.layer.addSublayer(self.avPlayerLayer)
self.player.play()
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { [weak self] _ in
self?.player?.seek(to: CMTime.zero)
self?.player?.play()
}
}
}
我知道一次加载和播放 6 个视频显然会占用大量内存,所以我尝试只播放 1 个视频而其他 5 个单元格为空,但这也使用了大约 100+ mb 的内存一旦我开始上下滚动。任何帮助将不胜感激。
尝试使用 Xcode 中的内存调试器。检查是否有 类 似乎只增加了数量。它可能会泄漏,因为您每次都创建一个新的 AVPlayer 并且永远不会停止前一个。
您不必每次都实例化 AVPlayer。
private lazy var player: AVPlayer = AVPlayer(playerItem: nil)
private lazy var playerLayer: AVPlayerLayer = {
let playerLayer = AVPlayerLayer(player: self.player)
playerLayer.videoGravity = .resizeAspectFill
return playerLayer
}()
override func awakeFromNib() {
super.awakeFromNib()
self.videoView.layer.addSublayer(self.playerLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
avPlayerLayer.frame = videoView.layer.bounds
}
现在 stopvid()
您可以暂停或呼叫 player.replaceCurrentItem(with: nil)
而在 playvid(url: String)
中你使用类似的东西:
let playerItem = AVPlayerItem(url: URL(string: url)!)
player.placeCurrentItem(with: playerItem)
player.play()
应该注意的是,由于我现在在 Windows 机器上,所以我无法 运行 这段代码,但根据文档,它应该可以工作。
我正在制作一个 iOS 应用程序,可以将其与带有视频源(无图像)的 Instagram 进行比较。我有一个 table 显示自定义 table 视图单元格,每个 table 视图单元格包含一个使用 AVKit 播放的视频。我现在有 6 个单元格正在加载,它使用了令人难以置信的内存量来显示它们。像 facebook、instagram 或 vine 这样的应用程序如何在不使用大量内存的情况下显示这么多视频?
下面是我目前使用的代码。
var cells: [VideoCell] = []
var cellPostkeys: [String] = []
@IBOutlet weak var feedTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
feedTableView.delegate = self
feedTableView.dataSource = self
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 250
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videoURLs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let url = videoURLs[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "testcell") as? VideoCell {
if (cellPostkeys.contains(url)) {
let index = cellPostkeys.firstIndex(of: url)
cells[index!] = cell
} else {
cells.append(cell)
cellPostkeys.append(url)
}
cell.playvid(url: url)
return cell
} else {
return VideoCell()
}
}
}
这是我自定义 table 视图单元格的代码
class VideoCell: UITableViewCell {
@IBOutlet weak var videoView: UIView!
var player : AVPlayer!
var avPlayerLayer : AVPlayerLayer!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
override func layoutSubviews() {
super.layoutSubviews()
//
}
func stopvid() {
self.player = nil
self.avPlayerLayer = nil
}
func playvid(url: String) {
self.player = AVPlayer(url: URL(string: url)!)
self.avPlayerLayer = AVPlayerLayer(player: self.player)
self.avPlayerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
self.player.automaticallyWaitsToMinimizeStalling = false
avPlayerLayer.frame = videoView.layer.bounds;
self.videoView.layer.addSublayer(self.avPlayerLayer)
self.player.play()
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { [weak self] _ in
self?.player?.seek(to: CMTime.zero)
self?.player?.play()
}
}
}
我知道一次加载和播放 6 个视频显然会占用大量内存,所以我尝试只播放 1 个视频而其他 5 个单元格为空,但这也使用了大约 100+ mb 的内存一旦我开始上下滚动。任何帮助将不胜感激。
尝试使用 Xcode 中的内存调试器。检查是否有 类 似乎只增加了数量。它可能会泄漏,因为您每次都创建一个新的 AVPlayer 并且永远不会停止前一个。
您不必每次都实例化 AVPlayer。
private lazy var player: AVPlayer = AVPlayer(playerItem: nil)
private lazy var playerLayer: AVPlayerLayer = {
let playerLayer = AVPlayerLayer(player: self.player)
playerLayer.videoGravity = .resizeAspectFill
return playerLayer
}()
override func awakeFromNib() {
super.awakeFromNib()
self.videoView.layer.addSublayer(self.playerLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
avPlayerLayer.frame = videoView.layer.bounds
}
现在 stopvid()
您可以暂停或呼叫 player.replaceCurrentItem(with: nil)
而在 playvid(url: String)
中你使用类似的东西:
let playerItem = AVPlayerItem(url: URL(string: url)!)
player.placeCurrentItem(with: playerItem)
player.play()
应该注意的是,由于我现在在 Windows 机器上,所以我无法 运行 这段代码,但根据文档,它应该可以工作。