gpt4 book ai didi

ios - 使用嵌套 ScrollView 时滚动获取 "stuck"

转载 作者:可可西里 更新时间:2023-11-01 03:20:33 24 4
gpt4 key购买 nike

问题描述:
我有一个用于浏览嵌套图像的 iOS 项目 UIScrollViews其灵感来自著名的 Apple 的 PhotoScroller .
问题是当图像在宽度或高度上缩放时,有时滚动只是“卡住”。这是它在 iPhone 4s 上的外观示例尺寸图片935x1400高度缩放:
(我开始向左拖动,但 ScrollView 会立即放弃此操作,图像会“卡住”)
Scroll problem
解决方法:
通过在缩放后将内部 ScrollView 的内容大小调整为最接近的整数,我找到了一种解决方法:

// Inside ImageScrollView.m

- (void)setZoomScale:(CGFloat)zoomScale
{
[super setZoomScale:zoomScale];
[self fixContentSizeForScrollingIfNecessary];
}

- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated
{
[super zoomToRect:rect animated:animated];
[self fixContentSizeForScrollingIfNecessary];
}

- (void)fixContentSizeForScrollingIfNecessary
{
if (SYSTEM_VERSION_LESS_THAN(@"10.2"))
{
CGSize content = self.contentSize;
content.width = rint(content.width);
content.height = rint(content.height);
self.contentSize = content;
}
}
但是这个修复并不完美——现在一些图像的侧面显示有一个像素宽的条纹。例如,在 iPhone 6尺寸图片 690x14300它显示在底部:
iPhone 6
另外,奇怪的是,我可以在 iOS 7.0 - 10.1 上重现这个问题。 ,但在 iOS 10.2 上一切正常和更大。
题:
那么,我做错了什么?我的修复可以改进吗?
测试项目:
我创建了简单的测试项目来说明所描述的问题 - NestedScrollingProblems .请注意我的 ImageScrollView 版本与 Apple 版本略有不同,因为我应用了另一条缩放规则。此外,默认情况下已注释掉解决方法。
(项目代码有点乱,抱歉)

最佳答案

无法对帖子发表评论(还没有足够的代表)。

但是从它的外观(Apple 的文档)来看,这个项目 deinits滚动图像,然后 re-inits当它们将被加载时(见 UIScrollView.m 中的第 350 行)。而且我还注意到 ImageScrollView.m 里面的评论(第 346 行)明确指出此类旨在避免缓存。这是演示的实用方法,但不适用于生产或实际应用程序,这些应用程序需要像您想要的那样考虑 ui 加载速度。

我还注意到您的应用程序必须进一步滚动才能进行分页。这要么是代码中的一些错误,要么是滞后本身导致主线程无法流畅地运行分页。或者,如果您打算设置如此宽的分页阈值……我建议减少它以获得更好的用户体验,因为现代智能手机的屏幕比 iPhone 4S 的屏幕宽得多。

为了解决这个问题,

我找到了这个 post (波纹管)在 SO 上,它似乎有一个相当不错的 obj-c 方法来缓存,并在应用程序启动后从这样的缓存中获取图像数据。您也应该能够非常简单地将其用于发布后方法,或者甚至将其与网络一起使用以从网络下载图像。您只需要确保您的 UIImage View 正确链接到您使用的 url 字符串,或者通过每个 ImageView 的一组自定义字符串变量,或者通过将 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];
}

为了不改变你所做的太多,似乎通过改变 displayImageWithInfo ImageScrollview.m 里面的方法改为下面的方法(使用缓存方法),在初始加载后似乎效果更好。如果我是你,我也会更进一步,在 Controller 的 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];
}

我还建议解决此问题,而无需在滚动时从其 super View 中删除 View 。添加 View 是一项非常繁重的任务。再加上图像加载,对于像智能手机上的小 CPU 来说可能会非常沉重(因为它们还没有 GPU ......)。为了强调这一点,Apple 甚至提到它一旦显示 UIImages 就不会重新渲染,措辞很微妙 here ,但它显然没有提到优化删除,然后在显示一次后重新添加和渲染 View (例如在这种情况下)。我认为这里的预期用途是显示 ImageView ,只需将其更改为 image显示 Controller 之后的元素。

Although image objects support all platform-native image formats, it is recommended that you use PNG or JPEG files for most images in your app. Image objects are optimized for reading and displaying both formats, and those formats offer better performance than most other image formats.



这就是为什么 View 通常在任何可见加载方法(如 viewWillAppear)之前在其 super View 上添加/初始化的原因。和 viewDidAppear ,或者如果它是在初始加载后完成的,它们很少被取消初始化,它们的内容通常是唯一改变的东西,即使如此,它通常也是异步完成的(如果从网络下载),或者它是从缓存中完成的,它可以也可以使用一些初始化程序自动完成(您可以将其添加到我推荐的内容中):

Use the imageNamed:inBundle:compatibleWithTraitCollection: method (or the imageNamed: method) to create an image from an image asset or image file located in your app’s main bundle (or some other known bundle). Because these methods cache the image data automatically, they are especially recommended for images that you use frequently.



就个人而言,我会尝试采用 UICollectionViews 的方法。 .值得注意的是,当 View 滚出窗口时,它们具有自动处理内容缓存的委托(delegate)(这正是本演示的内容)。您也可以向这些方法添加自定义代码,以更好地控制这些 View 上的滚动效果。一开始它们可能有点难以理解,但我可以证明,您在此处尝试完成的工作可以使用此演示使用的一小部分代码进行复制。我还认为这个演示是在 2012 年构建的作为一个提示..这是一个非常古老的演示,并且 UICollectionViews 出现在这个演示上次更新时。所以我想说这就是 Apple 一直以来的目标,因为所有面向内容的 UIView 子类无论如何都有某种继承自 UIScrollView
(UICollectionView、UITableView、UITextView 等)。值得一看! UICollectionViews .

关于ios - 使用嵌套 ScrollView 时滚动获取 "stuck",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44092165/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com