覆盖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以上是关于覆盖scrollViewDidScroll时的问题,但不是UIScrollViewDelegate的所有其他方法的主要内容,如果未能解决你的问题,请参考以下文章
在 UIWebView 中没有调用 scrollViewDidScroll
- (void)scrollViewDidScroll:(UIScrollView *)scrollView 在 iOS 8 中太慢了