- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我目前正在开发一个 iPad 应用程序,它将大约 250 个 UIImage
加载到 UIButton
中(然后更改颜色),创建世界地图 - 每个国家有自己的按钮和相应的图像 - 在加载游戏时。我遇到的问题是,在视网膜 iPad 上,应用程序在加载图像时使用了 ~650MB 的 RAM,这太疯狂了。
当应用最初加载游戏时,它使用以下代码将图像设置到按钮(Territory
是 UIButton
的子类)。
//Initialize the arrays of each territory and add an action to the territory
for (int i = (int)territoryArray.count - 1; i >= 0; i--) {
@autoreleasepool {
//Cast the object into a territory object
Territory *ter = (Territory *)[territoryArray objectAtIndex:i];
//Set the territory's image
[ter setImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@T%i.png", [defaults objectForKey:@"Current_Map"], i + 1] ofType:nil]] forState:UIControlStateNormal];
}
}
这会导致以下内存使用情况。尖峰在循环运行时出现,但即使该 block 被 @autoreleasepool
包围也不会消失。请注意,ImageIO
正在使用内存:
该屏幕截图是在各地区的图像文件中具有原始颜色时截取的。我正在使用 MGImageUtilities
中的 UIImage+Tint
库为图像着色。使用该库时,将使用以下代码:
[ter setImage:[[ter imageForState:UIControlStateNormal] imageTintedWithColor:[UIColor colorWithRed:[[colors objectAtIndex:0] floatValue]/255.0 green:[[colors objectAtIndex:1] floatValue]/255.0 blue:[[colors objectAtIndex:2] floatValue]/255.0 alpha:1.0]] forState:UIControlStateNormal];
在加载所有图像后,在另一个循环(包含在另一个函数中的 @autoreleasepool
中)使用此代码时,会发生以下内存使用情况。请注意,CG 光栅数据
正在使用内存。
我不知道为什么使用内存的东西不一样。
我posted a thread在 Apple Developer Forums 上也是这个问题的前奏。
我也联系过 Apple Developer TSI,他们推荐使用“lazy image loading”。我对此进行了调查,但还没有找到在非基于页面的 UIScrollView
上执行此操作的方法。
在这一点上,我几乎不知道如何解决这个问题。在数小时的时间里,我已经尝试了所有我能想到的方法来解决这个问题,但我似乎无法想出任何可行的解决方案。如果有人可以帮助我,我将不胜感激。如果您想查看更多信息或代码,请告诉我,我很乐意发布。预先感谢您的帮助。
编辑:
我一直在试验,我正在使用 scrollViewDidScroll:
中的以下代码。它似乎在工作,但内存没有被释放,它继续上升。想法?
CGRect currentF = [scrollView convertRect:scrollView.bounds toView:scrollView.contentView];
//Loop through all territories and determine which need to be rendered
for (int i = (int)territoryArray.count - 1; i >= 0; i--) {
@autoreleasepool {
//See if the territory is on-screen
if (CGRectIntersectsRect(currentF, [[territoryArray objectAtIndex:i] frame])) {
//See if the territory needs an image
if ([[territoryArray objectAtIndex:i] image] == nil) {
//Set the territory's image
[[territoryArray objectAtIndex:i] setImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@T%i.png", [defaults objectForKey:@"Current_Map"], i + 1] ofType:nil]] forState:UIControlStateNormal];
}
} else {
//Remove the territory's image, it is off-screen
[[territoryArray objectAtIndex:i] setImage:nil forState:UIControlStateNormal];
}
}
}
最佳答案
我发现,当我必须将图像加载到 ScrollView 中时,为了避免内存问题和应用程序的一般响应,您可以增量加载图像。这意味着,尽管 ScrollView 中可能有 250 张图像,但您无法同时看到它们。所以加载他可见的瓷砖,以及它下面的几行。您可以在滚动时加载其余内容。
编辑:这是一个例子。
-(void)scrollViewDidScroll:(UIScrollView *)myScrollView {
int currentPage = (1 + myScrollView.contentOffset.x / kXItemSpacingIphone);
for (ItemView* itemView in [self.itemRow subviews]){
if (itemView.tag >= currentPage-1 && itemView.tag <= currentPage+1)
{
//keep it visible
if (!itemView.isLoaded) {
[itemView layoutWithData:[self.items objectAtIndex:itemView.tag-1]];
}
}
else
{
//hide it
if (itemView.isLoaded) {
[itemView unloadData];
}
}
}
上面的代码将加载可见页面上方页面和下方页面的图像。我发现页面滚动有点不稳定。但我正在从网络加载图像,因此您可能会发现这工作得很好。
祝你好运!
编辑 2:
如果您的 ScrollView 没有设置分页,试试这个。
使我的 View Controller 成为 ScrollView 的委托(delegate)(如果您在代码中执行此操作,则必须修改 View Controller 的 .h 以使其符合 UIScrollViewDelegate)。
定义一个 scrollViewDidScroll 方法,(a) 确定 ScrollView 可见部分的框架; (b) 确定哪个 subview 与该可见部分相交; (c) 加载可见的项目,卸载不可见的项目。
它最终会看起来像这样。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// Determine the frame of the visible portion of the scrollview.
CGRect visibleScrollViewFrame = scrollView.bounds;
visibleScrollViewFrame.origin = scrollView.contentOffset;
// Now iterate through the various items, remove the ones that are not visible,
// and show the ones that are.
for (Item *itemObject in self.itemCollection)
{
// Determine the frame within the scrollview that the object does (or
// should) occupy.
CGRect itemObjectFrame = [self getItemObjectFrame:itemObject];
// see if those two frames intersect
if (CGRectIntersectsRect(visibleScrollViewFrame, itemObjectFrame))
{
// If it's visible, then load it (if it's not already).
// Personally, I have my object have a boolean property that
// tells me whether it's loaded or not. You can do this any
// way you want.
if (!itemObject.loaded)
[itemObject loadItem];
}
else
{
// If not, go ahead and unload it (if it's loaded) to conserve memory.
if (itemObject.loaded)
[itemObject unloadItem];
}
}
}
关于ios - 应用程序分配 650MB 的 RAM 以加载 CG 光栅数据 ~250 个 UIImages,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22952027/
如果我们想访问数组的元素 i,我们会这样做:i *(每个元素的大小)+ 数组的起始地址 = 我们需要访问的元素的内存位置。然后 CPU 直接访问 RAM 中的该位置。这是怎么发生的? 假设我要定位的内
考虑以下 python 代码 with open(sys.argv[2], 'r') as fin, \ open(sys.argv[3], 'w') as fout:
基本上我在 Centos 6.2 16GB 系统上运行我的世界服务器 我通过 rtoolkit 引导来启动我的服务器,现在我分配它使用 12GB,但它使用的 muc 比这多,我不知道为什么。我运行此命
我正在开发一个小型 x86 内核。我正在访问并尝试读取 GRUB 在多重引导 header 中提供的内存映射。我有一个 Intel i3 cpu 和 4 GiB 的 RAM。在这台机器上运行时,我正在
我有 3 GB 内存。有没有办法只为 C++ 应用程序分配 512MB 的 RAM? 否则 有没有办法暂时将我的 RAM 减少到 512MB 以进行测试? 谢谢,阿肖克 最佳答案 使用SetProce
我的一个 friend 告诉我,在 x86 架构上,DMA Controller 无法在两个不同的 RAM 位置之间传输。它只能在RAM和外设(如PCI总线)之间传输。 这是真的吗? 因为 AFAIK
做一些分析(内存和速度) 我一直被 win7 似乎分配的 RAM 正好是我要求的两倍这一事实所困扰...注意这是我第一次在 win7 上进行这样的主动分析,所以我真的不知道会发生什么。 我在 win7
我经常玩 retrofit 版的 Minecraft。这样做的一个缺点是,每当我启动 Minecraft 时,编译所有模组都需要花费大量时间。这可能需要大约 15 分钟左右的时间,在我看来,这太长了。
我想编写一个内核模块,可以通过 DMA 将数据从 RAM 传输到 RAM。有一些帖子讨论这个,但我真的不明白。有人说可能,也有人说不可能。 如果我对 ldd3 的理解是正确的,RAM 到 RAM 的复
我正在寻找一种方法来查找总内存和正在使用的内存的单个熟值输出。 gwmi Win32_OperatingSystem | select TotalVisibleMemorySize, FreePhys
我在 Heroku 上有一个网络应用程序,我试图了解添加具有 1GB RAM 的 Memcached 实例与向我的 Postgres 服务器添加 1GB RAM 之间的区别/权衡。 如果我添加一个 M
在我的例子中,我有一个包含大约 6000 个实例化类的字典,其中每个类都有 1000 个属性变量,所有类型都是字符串或字符串列表。当我建立这本字典时,我的 RAM 变得非常高。有没有一种方法可以在将字
我的问题是:如果您用完了所有可用的视频内存,并尝试创建新纹理 (SDL),是否会自动使用普通内存而不是视频内存?或者,您是否必须尝试使用使用普通 ram 的表面 (SDL)?如果您出于任何原因无法
我在从 ram 地址获取值时遇到问题。 我有一些限制,即它必须是 C 代码,并且存储信息的地址由 u32 值给出,例如 0x001c0080。 环境是ARM的,我用的是eclipse sdk。我怎样才
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a software
我正在尝试使用 GCC 编译器(标准 C)编译裸机应用程序。我使用 Cyclone V SoC 和 Cortex-A9 处理器。 eclipse DS-5。我收到这些错误 - “Region ram
如果 RAM 不是问题(我的服务器上有接近 200GB),是逐行读取更快还是将所有内容读入 RAM 并访问它?每行将是大约 200-500 个 unicode 字符的字符串。每个文件有近 200 万行
我在我的两台机器上运行以下命令: import os, sqlite3 import pandas as pd from feat_transform import filter_anevexp db
我正在尝试在我的一个项目中引入一些 CUDA 优化。但我认为我在这里做错了什么。我想实现一个简单的矩阵 vector 乘法 (result = matrix * vector)。但是当我想将结果复制回
#include #include #include #include #include #include using namespace std; char randomLetter()
我是一名优秀的程序员,十分优秀!