दिलचस्प पोस्ट
चर संयोजन के लिए एकल उद्धरण या दोहरे उद्धरण? मैं एक निजी विधि को लागू करने के लिए प्रतिबिंब का उपयोग कैसे करूं? PHP का उपयोग करके कई फाइल अपलोड कैसे करें अजगर-मटप्ललिब में 3 डी बहुभुज का प्लॉटिंग मैं पायथन टंकिनटर रूट विंडो से छुटकारा कैसे प्राप्त करूं? पायथन मल्टी प्रॉससेसिंग: मैं कई प्रक्रियाओं के बीच एक डिक्शनिस कैसे साझा करूं? Android के लिए Google डिस्क \ डॉक्स एपीआई Pthreads की स्थिति चर कार्यों को एक mutex की आवश्यकता क्यों है? बड़ी फ़ाइल प्रतिलिपि के दौरान प्रगति (कॉपी-आइटम और लेखन-प्रगति?) सरल एएसपी.नेट एमवीसी सीआरयूयूडी जावास्क्रिप्ट यूआई संवाद में खोलने / समापन दृश्य C # में लॉक कीवर्ड सी चार सरणी प्रारंभ जावा में एक विश्वव्यापी अद्वितीय पहचानकर्ता उत्पन्न करना कौन सी सबसे अच्छी विधि स्क्रिप्ट को दोहराव से आर। में सीसीवी फाइलों पर लागू करने के लिए है? बूलियन बनाम बीटसेट: कौन सा अधिक कुशल है?

आईओएस: मुझे कैसे पता चलेगा कि कोई संपत्ति केवीओ-शिकायत है?

कुंजी-मान अवलोकन प्रोग्रामिंग मार्गदर्शिका में , कुंजी-मान अवलोकन के लिए पंजीकृत विभाग का कहना है, "आमतौर पर एप्पल-आपूर्ति की गई चौखटे में गुण केवल केवीओ-संगत हैं यदि वे ऐसे दस्तावेज हैं।" लेकिन, मुझे दस्तावेज़ीकरण में कोई गुण नहीं मिला है जो केवीओ-संगत के रूप में प्रलेखित हैं। क्या आप मुझसे कुछ बात कर सकते हैं?

विशेष रूप से, मैं जानना चाहूंगा कि @property(nonatomic,retain) UIViewController *rootViewController के @property(nonatomic,retain) UIViewController *rootViewController@property(nonatomic,retain) UIViewController *rootViewController -संगत है। इसका कारण यह है कि मैं आईओएस <4 के लिए rootViewController लिए rootViewController प्रॉपर्टी जोड़ रहा हूं और जानना चाहता हूं कि मुझे इसे केवीओ-आज्ञाकारी बनाना चाहिए।

 @interface UIWindow (Additions) #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0 @property (nonatomic, retain) UIViewController *rootViewController; #endif; @end @implementation UIWindow (Additions) #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0 @dynamic rootViewController; - (void)setRootViewController:(UIViewController *)newRootViewController { if (newRootViewController != _rootViewController) { // Remove old views before adding the new one. for (UIView *subview in [self subviews]) { [subview removeFromSuperview]; } [_rootViewController release]; _rootViewController = newRootViewController; [_rootViewController retain]; [self addSubview:_rootViewController.view]; } } #endif @end 

Solutions Collecting From Web of "आईओएस: मुझे कैसे पता चलेगा कि कोई संपत्ति केवीओ-शिकायत है?"

लघु उत्तर: संख्या

लम्बी उत्तर: UIKit में कुछ भी केवीओ-आज्ञाकारी होने की गारंटी नहीं है यदि आपको लगता है कि एक संपत्ति काम करता है कि KVO- आईएनजी, आभारी रहें, यह unintentional है इसके अलावा: सावधान रहें यह भविष्य में बहुत अच्छी तरह से टूट सकता है

अगर आपको लगता है कि यह आपको कुछ चाहिए, तो कृपया एक वृद्धि अनुरोध दर्ज करें ।


आपके वास्तविक कोड के बारे में, यह स्वाभाविक रूप से दोषपूर्ण है इस तरीके से UIWindow को "rootViewController" सेटर जोड़ने का प्रयास न करें जब आप आईओएस 4 पर अपना कोड संकलित करेंगे तो यह टूट जाएगा, लेकिन किसी ने इसे आईओएस 5 डिवाइस पर चलाया है। चूंकि आपने 4.x एसडीके का इस्तेमाल करते हुए संकलित किया है, तो #if बयानों का मूल्यांकन सही होगा, जिसका अर्थ है कि आपकी श्रेणी पद्धति फेंकता द्विआधारी में शामिल की जाएगी। हालांकि, जब आप इसे आईओएस 5 डिवाइस पर चलाते हैं, तो आप अब एक विधि संघर्ष प्राप्त करने जा रहे हैं क्योंकि UIWindow पर दो विधियों का एक ही तरीका हस्ताक्षर होगा, और इसमें कोई गारंटी नहीं है कि किस का इस्तेमाल किया जाएगा

इस तरह के ढांचे के साथ पेंच मत करो यदि आपको यह करना है, तो उप-वर्ग का उपयोग करें यही कारण है कि वर्तमान में पेश किया जा रहा है


आपका उपवर्ग इस तरह से कुछ दिखाई देगा:

 @interface CustomWindow : UIWindow @property (nonatomic, retain) UIViewController *rootViewController; @end @implementation CustomWindow : UIWindow static BOOL UIWindowHasRootViewController = NO; @dynamic rootViewController; - (void)_findRootViewControllerMethod { static dispatch_once_t predicate; dispatch_once(&predicate, ^{ IMP uiwindowMethod = [UIWindow instanceMethodForSelector:@selector(setRootViewController:)]; IMP customWindowMethod = [CustomWindow instanceMethodForSelector:@selector(setRootViewController:)]; UIWindowHasRootViewController = (uiwindowMethod != NULL && uiwindowMethod != customWindowMethod); }); } - (UIViewController *)rootViewController { [self _findRootViewControllerMethod]; if (UIWindowHasRootViewController) { // this will be a compile error unless you forward declare the property // i'll leave as an exercise to the reader ;) return [super rootViewController]; } // return the one here on your subclass } - (void)setRootViewController:(UIViewController *)rootViewController { [self _findRootViewControllerMethod]; if (UIWindowHasRootViewController) { // this will be a compile error unless you forward declare the property // i'll leave as an exercise to the reader ;) [super setRootViewController:rootViewController]; } else { // set the one here on your subclass } } 

चेतावनी लागूकर्ता : मैंने इसे ब्राउज़र विंडो में टाइप किया था

डेविड डीलांग के समाधान के आधार पर, यह वही है जो मेरे साथ आया, और यह खूबसूरती से काम करता है।

असल में, मैंने UIWindow पर एक श्रेणी बनायी है और +load , मैं (रन-टाइम) [UIWindow instancesRespondToSelector:@selector(rootViewController)] कि क्या [UIWindow instancesRespondToSelector:@selector(rootViewController)] । यदि नहीं, तो rootViewController लिए rootViewController और सेटर विधियों को गतिशील रूप से जोड़ने के लिए मैं class_addMethod() का उपयोग class_addMethod() rootViewController । साथ ही, मैं objc_getAssociatedObject rootViewController के एक इंस्टेंस चर के रूप में rootViewController objc_setAssociatedObject को प्राप्त करने और सेट करने के लिए objc_getAssociatedObject और objc_setAssociatedObject का उपयोग करता objc_getAssociatedObject

 // UIWindow+Additions.h @interface UIWindow (Additions) @end // UIWindow+Additions.m #import "UIWindow+Additions.h" #include <objc/runtime.h> @implementation UIWindow (Additions) #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0 // Add rootViewController getter & setter. static UIViewController *rootViewControllerKey; UIViewController *rootViewController3(id self, SEL _cmd); void setRootViewController3(id self, SEL _cmd, UIViewController *newRootViewController); UIViewController *rootViewController3(id self, SEL _cmd) { return (UIViewController *)objc_getAssociatedObject(self, &rootViewControllerKey); } void setRootViewController3(id self, SEL _cmd, UIViewController *newRootViewController) { UIViewController *rootViewController = [self performSelector:@selector(rootViewController)]; if (newRootViewController != rootViewController) { // Remove old views before adding the new one. for (UIView *subview in [self subviews]) { [subview removeFromSuperview]; } objc_setAssociatedObject(self, &rootViewControllerKey, newRootViewController, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self addSubview:newRootViewController.view]; } } + (void)load { if (![UIWindow instancesRespondToSelector:@selector(rootViewController)]) { class_addMethod([self class], @selector(rootViewController), (IMP)rootViewController3, "@@:"); class_addMethod([self class], @selector(setRootViewController:), (IMP)setRootViewController3, "v@:@"); } } #endif @end 

एक श्रेणी के साथ एक उदाहरण चर परिभाषित करने के लिए एसोसिएटिव सन्दर्भ का उपयोग कर एक समाधान है। लेकिन, डेव डीएलओंग के अनुसार, यह काम नहीं करता, मुझे रन-टाइम (कंपाइल-टाइम) का उपयोग करना चाहिए, इसके लिए जांच करें

 // UIWindow+Additions.h @interface UIWindow (Addtions) #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0 @property (retain, nonatomic) UIViewController *rootViewController; #endif @end // UIWindow+Additions.m #import "UIWindow+Additions.h" #include <objc/runtime.h> @implementation UIWindow (Additions) #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0 @dynamic rootViewController; static UIViewController *rootViewControllerKey; - (UIViewController *)rootViewController { return (UIViewController *)objc_getAssociatedObject(self, &rootViewControllerKey); } - (void)setRootViewController:(UIViewController *)newRootViewController { UIViewController *rootViewController = self.rootViewController; if (newRootViewController != rootViewController) { // Remove old views before adding the new one. for (UIView *subview in [self subviews]) { [subview removeFromSuperview]; } [rootViewController release]; objc_setAssociatedObject(self, &rootViewControllerKey, newRootViewController, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [rootViewController retain]; [self addSubview:rootViewController.view]; } } #endif @end 

@ डेविड डीएलओंग की प्रतिक्रिया के आधार पर, मैं इस तरह एक साधारण उपवर्ग के साथ गया:

 // UIWindow3.h #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0 @interface UIWindow3 : UIWindow { } @property (nonatomic, retain) UIViewController *rootViewController; @end #endif // UIWindow3.m #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0 #import "UIWindow3.h" @implementation UIWindow3 @synthesize rootViewController; - (void)setRootViewController:(UIViewController *)newRootViewController { if (newRootViewController != rootViewController) { // Remove old views before adding the new one. for (UIView *subview in [self subviews]) { [subview removeFromSuperview]; } [rootViewController release]; rootViewController = newRootViewController; [rootViewController retain]; [self addSubview:rootViewController.view]; } } @end #endif 

हालांकि, यह भी मौजूदा कोड के माध्यम से जाने और UIWindow को UIWindow3 डालने के लिए सशर्त संकलन का उपयोग करने की आवश्यकता है, जहां कभी rootViewController तक पहुंचा जा रहा था। (ध्यान दें: मुझे लगता है कि @ CustomWindow के समाधान में ये अतिरिक्त परिवर्तन करने की आवश्यकता नहीं है बल्कि CustomWindow बजाय CustomWindow का उपयोग करते हुए हमेशा से।) इस प्रकार, अगर मैं (केवल आईओएस <4 के लिए) केवल rootViewController में rootViewController जोड़ सकता rootViewController एक श्रेणी के माध्यम से। मैं सहयोगी सन्दर्भों (केवल आईओएस <4) के लिए उपयोग कर एक श्रेणी के साथ ऐसा कर सकता हूं क्योंकि मुझे लगता है कि ऐसा लगता है कि यह सबसे भावपूर्ण समाधान होगा और टूलबॉक्स में जानने और सीखने की एक अच्छी तकनीक हो सकती है।