Проблемы при переопределении scrollViewDidScroll, но не всех других методов UIScrollViewDelegate

Хорошо, я провел все исследования по этой проблеме, но ни одно из существующих решений, похоже, не решает мою проблему, поэтому вот оно:

  • У меня есть собственный класс, который расширяет UIScrollView (и содержит UIView)
  • Я хотел бы переопределить метод scrollViewDidScroll из UIScrollViewDelegate (но не все методы)

Я уже пробовал реализовать код из этой проблемы: Как чтобы создать подкласс UIScrollView и сделать свойство делегата закрытым, но по какой-то причине он ничего не делает (пользовательский метод, который был переопределен, никогда не вызывается). Я также знаю, что вам не нужно реализовывать все методы из UIScrollViewDelegate, если вы создаете собственный класс делегата, реализующий протокол (согласно iPhone: нужно ли мне реализовать все методы для 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)» в консоли отладки.

Так что я немного не понимаю, что делать.


person Uzumaki Naruto    schedule 08.04.2012    source источник


Ответы (1)


У меня есть реализация Как создать подкласс UIScrollView и сделать частное свойство делегата, которое работает. Я предполагаю, почему ваш код ничего не сделал: дважды проверьте, действительно ли вы устанавливаете contentSize представления прокрутки на что-то большее, чем размер вашего представления. Если он меньше, то прокрутки нет, только подпрыгивание, а scrollViewDidScroll не вызывается.

Для вашего кода на самом деле у вас есть две проблемы в одной строке. Во-первых, свойство делегата UIScrollView имеет тип 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 значение больше, чем границы просмотра. В противном случае не будет ни прокрутки, ни вызовов делегатов.

person dtbow    schedule 10.04.2012
comment
Кстати, я установил для contentSize значение больше, чем общие границы представления объекта UIScrollView (по крайней мере, по вертикали - по горизонтали, я думаю, размер такой же). - person Uzumaki Naruto; 12.04.2012
comment
1. Я использую автоматический подсчет ссылок, поэтому не нужно освобождать / освобождать (по крайней мере, насколько я понимаю) 2. Я думаю, что свойство делегата должно быть указано как: id ‹NSObject, UIScrollViewDelegate› dlgt; - person Uzumaki Naruto; 12.04.2012
comment
Спасибо, это мне очень помогло. У меня тоже была проблема, что мой класс делегата не был сохранен. - person AlexWien; 09.06.2012