覆盖scrollViewDidScroll时的问题,但不是UIScrollViewDelegate的所有其他方法

Posted

技术标签:

【中文标题】覆盖scrollViewDidScroll时的问题,但不是UIScrollViewDelegate的所有其他方法【英文标题】:Problems when overriding scrollViewDidScroll, but not all the other methods of UIScrollViewDelegate 【发布时间】:2012-04-08 15:18:12 【问题描述】:

好的,所以我针对这个问题进行了所有研究,但现有的解决方案似乎都没有解决我的问题,所以这里是:

我有一个扩展 UIScrollView(并包含 UIView)的自定义类 我想覆盖 UIScrollViewDelegate 中的 scrollViewDidScroll 方法(但不是所有方法)

我已经尝试实现这个问题的代码:How to subclass UIScrollView and make the delegate property private,但由于某种原因,它没有做任何事情(被覆盖的自定义方法永远不会被调用)。我也知道,如果您创建一个实现协议的自定义委托类(根据iPhone: Do I need to implement all methods for UIScrollViewDelegate (or any delegate)),您不必实现 UIScrollViewDelegate 中的所有方法 - 但是当我这样做时:

MyScrollViewDelegate.h

@interface MyScrollViewDelegate: NSObject <UIScrollViewDelegate>

-(void)scrollViewDidScroll:(UIScrollView *)scrollView;

@end

MyScrollViewDelegate.m

@implementation MyScrollViewDelegate

-(void)scrollViewDidScroll:(UIScrollView *)scrollView

    NSLog(@"Custom scrollViewDidScroll called.");
    // -- some more custom code here --
    // ...


@end

在扩展 UIScrollView 的子类中

// this scrollview is initiated by the NIB
- (void)awakeFromNib

    ...
    [self setDelegate:[[MyScrollViewDelegate alloc] init]];

但是当它编译和运行时,当我尝试滚动可滚动视图时,它会崩溃,并在调试控制台中出现 EXC_BAD_ACCESS 和神秘的“(lldb)”消息。

所以我有点不知所措。

【问题讨论】:

【参考方案1】:

我确实有一个有效的How to subclass UIScrollView and make the delegate property private 实现。我猜你的代码为什么没有做任何事情:仔细检查你是否真的将滚动视图的 contentSize 设置为大于视图大小的值。如果它更小,则没有滚动,只是弹跳,并且不会调用 scrollViewDidScroll

对于您的代码,实际上一行中有两个问题。首先,UIScrollView 的delegate 属性是assign 类型。也就是说,如果委托类没有保留在其他地方,它会在一段时间内消失,你会得到EXC_BAD_ACCESS。其次,通过将 [[MyScrollViewDelegate alloc] init] 分配给委托而不释放该对象,您创建了一个引用计数为 1 并且永远不会被释放的孤儿对象。我的猜测是系统会在运行时识别出孤立对象并对其进行清理,然后在向委托发送消息时获得EXC_BAD_ACCESS

如果您更喜欢将您的版本与单独的委托一起使用,我将按如下方式进行修复:

@interface MyScrollView: UIScrollView

    id<NSObject, MyScrollViewDelegate> dlgt;
    ...

...
@end

@implementation MyScrollView
- (void)awakeFromNib

    ...
    dlgt = [[MyScrollViewDelegate alloc] init];
    [self setDelegate:dlgt];


-dealloc

    [dlgt release];
    [super dealloc];

@end

不过,不要忘记将 contentSize 设置为大于视图边界的值。否则将没有滚动和委托调用。

【讨论】:

顺便说一句,我确实将 contentSize 设置为大于整个 UIScrollView 对象的视图边界(至少垂直 - 水平我认为大小是相同的)。 1.我正在使用自动引用计数,因此不需要释放/释放(至少据我所知) 2. 我认为委托属性应列为:id dlgt; 谢谢,这对我帮助很大。我也遇到了我的委托类没有保留的问题。

以上是关于覆盖scrollViewDidScroll时的问题,但不是UIScrollViewDelegate的所有其他方法的主要内容,如果未能解决你的问题,请参考以下文章

方法和变量在继承时的覆盖和隐藏问题

scrollViewDidScroll:以编程方式滚动时?

覆盖 initWithCoder 时的无限循环

在 UIWebView 中没有调用 scrollViewDidScroll

- (void)scrollViewDidScroll:(UIScrollView *)scrollView 在 iOS 8 中太慢了

禁用 scrollViewDidScroll:滚动 UICollectionView 时 - iOS