从MPMediaLibrary加载大量歌曲到UITableView的启动性能优化问题
优化大型音乐库UITableView的启动速度
我之前在开发音乐库类App时,遇到过完全相同的性能瓶颈!一开始我采用的是一次性拉取全部歌曲信息并存入数组的方式,结果在装有10000+首歌曲的测试设备上,App启动耗时直接达到了5-10秒,用户体验极差。
后来我重构了UITableView的数据填充逻辑,完美解决了这个问题,App启动速度得到了显著提升,具体做法如下:
核心思路
放弃预加载全量歌曲数据的方案,改为在UITableView的cellForRowAt方法中按需动态获取对应位置的歌曲信息,把集中在启动阶段的大量数据处理操作,分散到表格滚动时的单元格渲染流程中。
代码实现对比
原来的低效实现
// 维护全量歌曲数组,启动时一次性加载 var allSongs: [Song] = [] override func viewDidLoad() { super.viewDidLoad() // 此处为性能瓶颈:遍历并加载10000+首歌曲的全部信息 allSongs = MusicLibrary.getAllSongs() tableView.reloadData() } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SongCell", for: indexPath) as! SongCell let song = allSongs[indexPath.row] cell.configure(with: song) return cell }
优化后的高效实现
// 不再维护全量歌曲数组 override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self tableView.delegate = self // 仅获取歌曲总数(此操作通常为轻量的元数据查询,速度极快) tableView.reloadData() } // 返回歌曲总数 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return MusicLibrary.getTotalSongCount() } // 按需获取当前行的歌曲信息 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SongCell", for: indexPath) as! SongCell let song = MusicLibrary.getSong(at: indexPath.row) cell.configure(with: song) return cell }
优化效果说明
这种方式彻底避免了启动阶段的大量IO和数据解析操作,App启动时只需要完成基础的UI初始化和获取歌曲总数,耗时几乎可以忽略不计。而歌曲的详细信息只会在对应的单元格即将出现在屏幕上时才被加载,完全不影响启动速度,同时也能保证滚动时的流畅性。
内容的提问来源于stack exchange,提问作者MrGreen
相关产品推荐
相关产品推荐

