Обнаруживать изменения в contentSize представления прокрутки UIWebView
Я пытаюсь установить UIView в нижней части содержимого UIScrollView, чтобы сделать так, чтобы я установил позицию представления высоты содержимого scrollview. Но мой вид прокрутки является подпредставлением UIWebView, поэтому при загрузке изображений высота содержимого изменяется, и мой вид, который должен быть в нижней части вида прокрутки, оказывается в середине...
Поэтому я ищу способ получать уведомления, когда изменяется размер содержимого прокрутки. Я попытался разделить его на подклассы и изменить установщик для содержимого для отправки 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
Любая идея, как сеттер должен быть разделен на подклассы?
Спасибо!
2 ответа
Возможно, вы можете использовать наблюдение значения ключа (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
Ваш подход наполовину правильный. Вы, несомненно, можете переопределить существующий метод через категорию, чего вы не можете сделать, хотя получаете доступ к ивару класса.
В этом случае вам нужен метод 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
Надеюсь, поможет.