无法评论帖子(还没有足够的代表)。
但是从它的外观(Apple 的文档)来看,这个项目 deinits 滚动上的图像,然后是 re-inits 当它们将被加载时(参见 UIScrollView.m 中的第 350 行)。而且我还注意到ImageScrollView.m(第 346 行)中的一条注释明确表示该类旨在避免缓存。对于演示来说,这是一种实用的方法,但不适用于生产环境或实际应用程序,这些应用程序考虑到了您想要的 ui 加载速度。
我还注意到,您的应用必须进一步滚动才能进行分页。这可能是代码中的一些错误,或者可能是滞后本身导致主线程无法流畅地运行分页。或者,如果您打算设置如此宽的分页阈值。我建议降低它以获得更好的用户体验,因为现代智能手机的屏幕比 iPhone 4S 的屏幕宽得多。
为了解决这个问题,
我在 SO 上发现了这个 post(如下),它似乎有一个相当不错的 obj-c 方法来缓存,并在应用程序启动后从这样的缓存中获取图像数据。您应该也可以很简单地将其用于发布后方法,甚至可以将其与网络一起使用以从网络下载图像。您只需要确保您的 UIImage 视图正确链接到您使用的 url 字符串,或者通过每个图像视图的一组自定义字符串变量,或者通过将 UImageView 子类化到自定义类中,并将缓存方法添加到它使您的代码看起来更简单。这是来自iOSfleer的帖子中的方法和 NSCahe 类
NSCache 类:
@interface Sample : NSObject
+ (Sample*)sharedInstance;
// set
- (void)cacheImage:(UIImage*)image forKey:(NSString*)key;
// get
- (UIImage*)getCachedImageForKey:(NSString*)key;
@end
#import "Sample.h"
static Sample *sharedInstance;
@interface Sample ()
@property (nonatomic, strong) NSCache *imageCache;
@end
@implementation Sample
+ (Sample*)sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[Sample alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
self.imageCache = [[NSCache alloc] init];
}
return self;
}
- (void)cacheImage:(UIImage*)image forKey:(NSString*)key {
[self.imageCache setObject:image forKey:key];
}
- (UIImage*)getCachedImageForKey:(NSString*)key {
return [self.imageCache objectForKey:key];
}
为了不改变你所做的太多,似乎通过将 ImageScrollview.m 中的 displayImageWithInfo 方法更改为以下一个(使用缓存方法),它似乎在之后工作得更好初始负载。如果我是你,我也会更进一步,并在控制器的 viewDidLoad 方法中实现一个循环样式的方法来立即缓存这些图像,以便在启动时更快地加载。但这取决于你。
- (void)displayImageWithInfo:(ImageItem*)imageInfo
{
CGSize imageSize = (CGSize){.width = imageInfo.width, .height = imageInfo.height};
// clear the previous imageView
[self.imageView removeFromSuperview];
self.imageView = nil;
// reset our zoomScale to 1.0 before doing any further calculations
self.zoomScale = 1.0;
self.imageView = [[UIImageView alloc] initWithFrame:(CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size = imageSize}];
UIImage *image = [[Sample sharedInstance] getCachedImageForKey:imageInfo.path];
if(image)
{
NSLog(@"This is cached");
((UIImageView*)self.imageView).image = image;
}
else{
NSURL *imageURL = [NSURL URLWithString:imageInfo.path];
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:imageURL]];
if(image)
{
NSLog(@"Caching ....");
[[Sample sharedInstance] cacheImage:image forKey:imageInfo.path];
((UIImageView*)self.imageView).image = image;
}
}
[self addSubview:self.imageView];
[self configureForImageSize:imageSize];
}
我还建议在不从滚动的超级视图中删除视图的情况下解决此问题。添加视图是一项非常繁重的任务。再加上图像加载,对于像智能手机这样的小型 CPU 来说可能会非常沉重(因为它们还没有 GPU ......)。为了强调这一点,Apple 甚至提到它不会在 UIImages 显示后重新渲染它们,措辞很微妙here,但它显然没有提到优化的删除然后重新添加和渲染视图后显示一次(例如在这种情况下)。我认为这里的预期用途是显示ImageView,然后在显示控制器后简单地将其更改为image元素。
虽然图像对象支持所有平台原生图像格式,但它
建议您对您的大多数图像使用 PNG 或 JPEG 文件
应用程序。图像对象针对阅读和显示进行了优化
格式,并且这些格式提供比大多数其他格式更好的性能
图像格式。
这就是为什么视图通常在任何可见加载方法(如viewWillAppear 和viewDidAppear)之前在其超级视图上添加/初始化的原因,或者如果在初始加载后完成,它们很少被取消初始化,它们的内容通常是唯一改变的东西,即便如此,它通常是异步完成的(如果从网络下载),或者它是从缓存中完成的,也可以使用一些初始化程序自动完成(你可以将它添加到我推荐的内容中):
使用 imageNamed:inBundle:compatibleWithTraitCollection: 方法(或
imageNamed: 方法)从图像资产创建图像或
位于应用程序主包中的图像文件(或其他一些已知的
捆)。因为这些方法会自动缓存图像数据,
特别推荐用于您经常使用的图片。
就个人而言,我会尝试采用UICollectionViews 的方法。值得注意的是,当视图滚动出窗口时,它们具有自动处理内容缓存的委托(这正是这个演示的内容)。您也可以向这些方法添加自定义代码,以更好地控制这些视图的滚动效果。一开始它们可能有点难以理解,但我可以证明你在这里尝试完成的工作可以用这个演示使用的一小部分代码来复制。我还认为这个演示是在 2012 年构建的这一事实作为提示.. 这是一个非常古老的演示,并且 UICollectionViews 出现在这个演示最后一次更新的时候。所以我想说这就是苹果一直以来的目标,因为所有面向内容的 UIView 子类都从 UIScrollView 继承了某种类型
(UICollectionView、UITableView、UITextView 等)。值得一看! UICollectionViews.