1

所以我正在开发一个基本上执行以下操作的 iOS 应用程序:在 iPhone 上它是一个UITabBarController带有五个选项卡的,在 iPad 上我有一个UISplitViewControllerMKMapView右侧有一个UITabBarController,在左侧有四个选项卡。该应用程序使用 ARC。

假设我们在谈论景点。
根据用户所在的当前城市,我的应用程序会将该城市的所有景点下载到设备上。一旦下载了某个景象,它就会存储在我的本地数据库中,因此用户不必再次下载它。如果用户搜索另一个城市,则会下载该城市的所有景点。等等。所有保存的景点都将在 tableView 或 mapView 中列出,按城市排序。

一个视线包括:

  • 1-10 张图片
  • 元信息(标题、副标题、名称、描述、地址、城市、国家、评级、ID、纬度、经度……)
  • 它属于 1-n 个类别/标签

该应用程序允许用户创建新景点、为其拍照、填写其元信息并将其上传到我的网络服务器。

只要只下载了少量景点,所有这些都可以正常工作。本地保存了 40 多个景点,我收到内存警告,应用程序退出。问题是该应用程序旨在浏览大量的景点,几百个。

现在我想知道一些处理此类内存问题的技术。

我想我的问题是,随着我的应用程序的启动,所有本地保存的景点都被加载到一个数组中,作为 tableView 或 mapView 的数据源。但是因为我想展示它们,所以除了这样做之外别无他法。

其他应用程序如何处理由多个图像和许多元信息或类似信息组成的大量自定义对象?是否存在处理此类问题的某种最佳实践?

非常感谢您!

4

3 回答 3

3

关键概念是您不应将所有图像加载到数组/字典中。最多,您应该只加载对这些图像的引用(例如,如果图像在Documents文件夹中,只需加载图像的路径/URL)。然后你的 UI 应该UIImage为它需要在任何给定点呈现 UI 的那些图像创建。

如果您使用的是表格视图或集合视图,iOS 会非常优雅地处理这个问题,调用您的数据源cellForRowAtIndexPath,并且只有在那时您才应该创建UIImage. 并且当单元格滚动时,如果您遵循典型的cellForRowAtIndexPath实现,我们将在表中的另一行重复使用该单元格,您将image使用 new 重新分配单元格的UIImage,并且假设旧图像可能不会有任何更强的引用,它将被释放,图像占用的内存将被释放。

一些额外的想法:

  1. 你说信息被下载到你的本地数据库中。您是在下载图像的 URL,还是实际上将图像本身放入数据库中。以我的经验,如果您处理的不是非常小的缩略图,您不想将图像保存在数据库本身中(因为 iOS 数据库在保存大 blob 方面效率很低),您会看到性能受到打击。例如,如果图像大于 100kb,您可能希望将图像下载到您的文档文件夹,并且只将图像的文件 URL/路径存储在数据库中。

  2. 如果您的应用程序一次显示大量图像(例如 iPad 应用程序并且您有一个可以显示的照片缩略图浏览器,例如一次显示 20 多张图像),您可能需要确保您正在加载的图像您的 UI 大小合适。例如,虽然 iOS 可以优雅地拍摄高分辨率图像并通过一个小UIImageView的 with向您显示缩略图UIViewContentModeAspectFill,但这可能是对内存的过度使用。我使用图像大小调整算法将图像大小调整为适合我的 UI 的大小,从而节省内存。如果您的图像很大或同时显示大量缩略图,您只需要担心这一点。

  3. 一旦您更改您的应用程序以将图像动态加载到UIImage对象中,您可能会对迄今为止可能没有经历过的其他性能注意事项变得敏感。典型的解决方案是使用缓存,将最近加载的图像保存在NSCache对象中,但如果设备内存不足,缓存将自动清空。所以这是两全其美的;当您一次加载所有图像时您习惯于体验的性能,但对优雅地处理低内存情况具有更高的敏感性。顺便说一句,像这样的第三方类SDWebImage会自动为您进行缓存。

于 2013-05-26T05:47:47.710 回答
2

我处理大量图像的方法是使用

https://github.com/rs/SDWebImage

它为您缓存图像、下载它们并将缓存全部转储到一个单独的线程上,因此您不必考虑这些东西。

于 2013-05-25T21:12:55.410 回答
1

您必须仅加载要显示的数据的一些信息,例如 ID、标题,您将用于填充初始信息,而其余信息(如图像)则需要在后台加载,并且准备好后更新,您可以查看以下答案,例如:

UICollectionView 滚动很慢

此外,当您的数据未显示在屏幕上时,您必须注意不要保留所有信息。

于 2013-05-25T21:00:59.367 回答