Ios -[UIScrollView zoomToRect:animated:]contentSize时的怪异行为<;大小

Ios -[UIScrollView zoomToRect:animated:]contentSize时的怪异行为<;大小,ios,objective-c,uiscrollview,Ios,Objective C,Uiscrollview,有人能准确描述-[UIScrollView zoomToRect:animated:][/code>的行为吗?这种方法看起来确实做了一些复杂的事情,但苹果公司关于它的文档非常稀少 当内容大小在宽度和/或高度上小于滚动视图的大小时,这种方法会出现不可预测的行为。在某些情况下,此方法会导致滚动视图在其应为0时具有负内容偏移。通过稍微不同的矩形,它将内容偏移量保留为0,这与我预期的一样 为了演示这种奇怪的行为,我设置了一个示例项目,其中包含一个大小为(200200)的滚动视图,其中包含一个大小为(10

有人能准确描述
-[UIScrollView zoomToRect:animated:][/code>的行为吗?这种方法看起来确实做了一些复杂的事情,但苹果公司关于它的文档非常稀少

当内容大小在宽度和/或高度上小于滚动视图的大小时,这种方法会出现不可预测的行为。在某些情况下,此方法会导致滚动视图在其应为0时具有负内容偏移。通过稍微不同的矩形,它将内容偏移量保留为0,这与我预期的一样

为了演示这种奇怪的行为,我设置了一个示例项目,其中包含一个大小为(200200)的滚动视图,其中包含一个大小为(100100)内容视图。我希望缩放到内容视图的rect((0,0)、(200,200))时,内容应保留在左上角(即不应发生任何事情)。但是,它实际上会导致内容滚动到滚动视图边界的右下角(内容偏移(-100,-100))。为什么会发生这种情况

以下是我的示例项目中的代码:

@implementation RootViewController

- (void)loadView {
    self.view = [[UIView alloc] init];

    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    self.scrollView.delegate = self;
    self.scrollView.backgroundColor = [UIColor whiteColor];
    self.scrollView.minimumZoomScale = .5;
    self.scrollView.maximumZoomScale = 4;

    self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    self.contentView.backgroundColor = [UIColor redColor];
    [self.contentView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)]];

    [self.scrollView addSubview:self.contentView];
    self.scrollView.contentSize = self.contentView.frame.size;
    [self.view addSubview:self.scrollView];
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return self.contentView;
}

- (void)handleTap {
    [self.scrollView zoomToRect:CGRectMake(0, 0, 200, 200) animated:YES]; // Try changing to 199, 199 to get completely different behavior
}

@end

谢谢你的见解!现在我猜,
UIScrollView
的设计并不是为了显示小于自身大小的内容。我的使用案例是,我的内容视图可能比滚动视图宽,但高度较短,并且我需要能够以编程方式滚动到此内容视图的右端或左端。

如果有人想知道,在这种情况下我可能会这样做。我将看看它是否与我在现实项目中实现的scroll view子类的单元测试配合得很好。然而,这并没有回答最初的问题“有人能准确地描述
-[UIScrollView zoomToRect:animated:
”所以我仍然希望得到更多的答案

好吧,下面是(我讨厌这样的黑客):

编辑:不幸的是,这有一个不幸的副作用,那就是你不能再在应该允许的较大图像的左侧反弹滚动(需要负内容偏移)。我将为我的用例寻找另一个解决方案


edit2:在进行
-zoomToRect:animated:
动画时,我仅通过禁用负内容偏移来避免上述副作用。我声明了一个
BOOL
属性,在调用
-zoomToRect:animated:
之前将其设置为
YES
,如果
animated
NO
,则之后将其设置回
NO
。否则,我会在
-scrollViewDiEndScrollingAnimation:
期间将属性设置为
NO
(如果
-zoomToRect:animated:
没有引起任何比例变化,则调用该属性)和
-ScrollViewDiEndZooming:withView:atScale:
(如果
-zoomToRect:animated:
确实引起了比例变化,则调用该属性)。这是一种黑客解决方案,我担心它可能会在未来的iOS版本中崩溃,但至少我有单元测试支持:)

除非有人有更好的答案,我将得出结论,当生成的
contentSize
小于任一维度的
界限
大小时,调用
-zoomToRect:animated:
具有未定义的结果。换句话说,如果您希望安全,内容应该大于滚动视图。

内容大小小于边界有什么意义?将未使用的维度设置为与边界匹配,然后继续。哦,iOS将允许您通过滚动到用户无法滚动到的位置来挂起自己。解决方案:不要这样做。@jaggedcow是的,我正在设置
contentSize
。即使在这种退化的情况下,我也希望将内容放在左上角。对于您的用例,为什么要使用zoomToRect:而不是scrollToRect:或者只是设置contentOffset?这可能会帮助您查看我的示例:演示如何在保持可缩放视图居中的同时允许缩放。您不需要两种方法;第一个调用第二个。根据我的测试,第一个不调用第二个是的,你是对的,我把它倒过来了:第二个调用第一个。
@implementation TBScrollView // Subclass of UIScrollView

- (void)setContentOffset:(CGPoint)contentOffset {
    contentOffset.x = MAX(contentOffset.x, 0);
    contentOffset.y = MAX(contentOffset.y, 0);
    [super setContentOffset:contentOffset];
}

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated {
    contentOffset.x = MAX(contentOffset.x, 0);
    contentOffset.y = MAX(contentOffset.y, 0);
    [super setContentOffset:contentOffset animated:animated];
}

@end