2012-11-08 26 views
12

मैं UIScrollView की सामग्री के नीचे एक UIView सेट करने का प्रयास कर रहा हूं, इसलिए मैं दृश्य की स्थिति को स्क्रॉलव्यू के कंटेंसिज हेगथ ​​पर सेट करता हूं। लेकिन मेरा स्क्रॉलव्यू UIWebView का एक सबव्यूव है, इसलिए जब छवियों को लोड किया जाता है, तो सामग्री को हेगथ ​​बदलता है और स्क्रॉलव्यू के निचले भाग में मेरा दृश्य मध्य में समाप्त होता है ...UIWebView के स्क्रॉल व्यू की सामग्री में परिवर्तनों का पता लगाएं आकार

तो मैं एक रास्ता तलाश रहा हूं जब स्क्रॉलव्यू की सामग्री बदलती है तो अधिसूचित किया जाना चाहिए। कह

@implementation UIScrollView (Height) 

-(void)setContentSize:(CGSize)contentSize 
{ 
    _contentSize=contentSize; 
    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"scrollViewContentSizeChanged" object:nil]]; 
} 

@end 

लेकिन संकलन पर मैं मिलता है और त्रुटि:

"_OBJC_IVAR _ $ _ UIScrollView._contentSize", से संदर्भित मैं इसे उपवर्ग और एक NSNotification भेजने के लिए contensize के लिए सेटर को बदलने के लिए कोशिश की है : - [UIScrollView (ऊँचाइ) setContentSize:] में MyClass.o ld: प्रतीक (रों) नहीं वास्तुकला ARMv7

किसी भी विचार कैसे सेटर subclassed किया जाना चाहिए के लिए मिला?

धन्यवाद!

उत्तर

28

शायद आप सामग्री आकार में परिवर्तनों का पता लगाने के लिए कुंजी-मूल्य अवलोकन (केवीओ) का उपयोग कर सकते हैं। मैं यह कोशिश की है नहीं, लेकिन कोड इस तरह दिखना चाहिए:

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 विधि के बारे में अधिक पढ़ सकते हैं: http://www.mikeash.com/pyblog/friday-qa-2010-01-29-method-replacement-for-fun-and-profit.html

मुझे लगता है कि इस swizzling के लिए सबसे लोकप्रिय कोड है: https://github.com/rentzsch/jrswizzle

+0

मेरी त्रुटि को इंगित करने के लिए धन्यवाद। उत्तर हटा दिया :) –

+1

केवीओ एक आकर्षण की तरह काम करता है, बहुत बहुत धन्यवाद! – Abel

+0

@rob mayoff क्या आप इसे स्विफ्ट 3 पर साझा कर सकते हैं? –

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

मैंने वही किया। प्रतिक्रिया के लिए धन्यवाद। –