Обнаруживать изменения в представлении прокрутки UIWebView contentSize
Я пытаюсь установить UIView в нижней части содержимого UIScrollView, сделайте так, чтобы я установил позицию представления в скобку scrollview. Но мой scrollview является подвидным интерфейсом UIWebView, поэтому при загрузке изображений изменяется размер содержимого и мое представление, которое должно быть в нижней части прокрутки, заканчивается посередине...
Итак, я ищу способ уведомления при изменении содержимого прокрутки. Я попытался подклассифицировать его и изменить setter для contensize, чтобы отправить NSNotification:
@implementation UIScrollView (Height)
-(void)setContentSize:(CGSize)contentSize
{
_contentSize=contentSize;
[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"scrollViewContentSizeChanged" object:nil]];
}
@end
Но при компиляции я получаю сообщение об ошибке:
"_ OBJC_IVAR _ $_ UIScrollView._contentSize", на который ссылаются: - [UIScrollView (Heigth) setContentSize:] в MyClass.o ld: символ не найден для архитектуры armv7
Любая идея, как сеттер должен быть подклассом?
Спасибо!
Ответы
Ответ 1
Возможно, вы можете использовать наблюдение за ключом (KVO) для обнаружения изменений в размере содержимого. Я не пробовал, но код должен выглядеть так:
static int kObservingContentSizeChangesContext;
- (void)startObservingContentSizeChangesInWebView:(UIWebView *)webView {
[webView.scrollView addObserver:self forKeyPath:@"contentSize" options:0 context:&kObservingContentSizeChangesContext];
}
- (void)stopObservingContentSizeChangesInWebView:(UIWebView *)webView {
[webView.scrollView removeObserver:self forKeyPath:@"contentSize" context:&kObservingContentSizeChangesContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == &kObservingContentSizeChangesContext) {
UIScrollView *scrollView = object;
NSLog(@"%@ contentSize changed to %@", scrollView, NSStringFromCGSize(scrollView.contentSize));
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
Если это не сработает, вам может потребоваться выполнить метод setContentSize:
. Метод swizzling позволяет методу замещения вызывать оригинальный метод, который вам нужно сделать, чтобы передать новый размер содержимого в прокрутку.
Подробнее о методах swizzling вы можете прочитать здесь: http://www.mikeash.com/pyblog/friday-qa-2010-01-29-method-replacement-for-fun-and-profit.html
Я думаю, что это самый популярный код для swizzling: https://github.com/rentzsch/jrswizzle
Ответ 2
Ваш подход наполовину правильный. Вы, безусловно, можете переопределить существующий метод через категорию, чего вы не можете сделать, хотя и обращаетесь к ivar класса.
В этом случае вам нужен метод swizzling: вы переопределяете setContentSize
и в то же время сохраняете ссылку на исходную реализацию метода, поэтому вы можете вызвать его, чтобы установить значение _contentSize
.
Вот код, который вы могли бы использовать, с комментариями:
@implementation UIScrollView (Height)
// -- this method is a generic swizzling workhorse
// -- it will swap one method impl with another and keep the old one
// under your own impl name
+ (void)swizzleMethod:(SEL)originalSel andMethod:(SEL)swizzledSel {
Method original = class_getInstanceMethod(self, originalSel);
Method swizzled = class_getInstanceMethod(self, swizzledSel);
if (original && swizzled)
method_exchangeImplementations(original, swizzled);
else
NSLog(@"Swizzling Fault: methods not found.");
}
//-- this is called on the very moment when the categoty is loaded
//-- and it will ensure the swizzling is done; as you see, I am swapping
//-- setContentSize and setContentSizeSwizzled;
+ (void)load {
[self swizzleMethod:@selector(setContentSize:) andMethod:@selector(setContentSizeSwizzled:)];
}
//-- this is my setContentSizeSwizzled implementation;
//-- I can still call the original implementation of the method
//-- which will be avaiable (*after swizzling*) as setContentSizeSwizzled
//-- this is a bit counterintuitive, but correct!
- (void)setContentSizeSwizzled:(CGSize)contentSize
{
[self setContentSizeSwizzled:contentSize];
[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"scrollViewContentSizeChanged" object:nil]];
}
@end
Надеюсь, что это поможет.