2012-11-08 6 views
12

UIScrollViewのコンテンツの一番下にUIViewを設定しようとしていますので、ビューの位置をscrollviewのcontensize heigthに設定してください。しかし、私のscrollviewは、UIWebViewのサブビューですので、画像がロードされると、内容の高さが変わり、スクロールビューの一番下にあるはずのビューが中間になります。UIWebViewのスクロールビューのcontentSizeへの変更を検出します。

私は方法を探していますスクロールビューの内容が変更されたときに通知されます。私はそれをサブクラス化し、NSNotificationを送信するcontensize用セッターを変更しようとしました:

@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中:記号(S)

のARMv7アーキテクチャ用セッターをサブクラス化する方法を任意のアイデアを発見していませんか?

ありがとうございます!

答えて

28

おそらく、キー値監視(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:方法をスウィズルする必要があるかもしれません。メソッドのスウィズルでは、新しいメソッドのサイズをスクロールビューに渡すために、元のメソッドを呼び出すことができます。

あなたがここにスウィズル方法についての詳細を読むことができます:http://www.mikeash.com/pyblog/friday-qa-2010-01-29-method-replacement-for-fun-and-profit.html

私は、これはスウィズリングのための最も人気のあるコードだと思う:https://github.com/rentzsch/jrswizzle

+0

私のエラーを指摘してくれてありがとう。答えを削除: –

+1

KVOは魅力のように動作し、非常にありがとう! – Abel

+0

@rob mayoffさん、swift3でこれを共有できますか? –

3

あなたのアプローチは半分正解です。クラスのivarにアクセスしているにも関わらず、既存のメソッドを確実にカテゴリでオーバーライドできます。

この場合、メソッドスウィズルが必要です。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 

はそれがお役に立てば幸いです。

+0

この素晴らしい答えをありがとう。しかし、私は質問があります。オブジェクトのインスタンスが複数ある場合、どのインスタンスがこのメソッドを呼び出すのかを検出できますか? –

+0

@OlcayErtaş: 'postNotificationName:object:userInfo:'を使用し、 'self'を' userInfo'や他の有用な情報として送ることができます:https://developer.apple.com/reference/foundation/nsnotificationcenter/1410608-postnotificationname?言語= objc – sergio

+0

私は同じことをしました。ご回答いただきありがとうございます。 –

関連する問題