IOS एप्लिकेशन में शीर्ष-सर्वाधिक दृश्य / विंडो का संदर्भ प्राप्त करना


97

मैं एक iOS एप्लिकेशन में सूचनाओं को प्रदर्शित करने के लिए एक पुन: प्रयोज्य रूपरेखा तैयार कर रहा हूं। मुझे लगता है कि एप्लिकेशन में अन्य सभी चीज़ों के शीर्ष पर अधिसूचना दृश्य जोड़े जाएंगे, जैसे कि UIAlertView। जब मैं उस प्रबंधक को इनिट करता हूं जो NSNotification ईवेंट्स के लिए सुनता है और प्रतिक्रिया में विचार जोड़ता है, तो मुझे एप्लिकेशन में शीर्ष-सर्वाधिक दृश्य का संदर्भ प्राप्त करना होगा। इस समय मेरे पास है:

_topView = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];

क्या यह किसी भी iOS एप्लिकेशन के लिए काम करेगा या शीर्ष दृश्य प्राप्त करने का उनका सुरक्षित / बेहतर तरीका है?

जवाबों:


36

आमतौर पर यह आपको शीर्ष दृश्य देगा, लेकिन इसकी कोई गारंटी नहीं है कि यह उपयोगकर्ता को दिखाई देता है। यह स्क्रीन से दूर हो सकता है, 0.0 का अल्फा है, या उदाहरण के लिए 0x0 का आकार हो सकता है।

यह भी हो सकता है कि keyWindow का कोई साक्षात्कार नहीं है, इसलिए आपको शायद उस पहले के लिए परीक्षण करना चाहिए। यह असामान्य होगा, लेकिन यह असंभव नहीं है।

UIWindow UIView का एक उपवर्ग है, इसलिए यदि आप यह सुनिश्चित करना चाहते हैं कि उपयोगकर्ता को आपकी सूचना दिखाई दे रही है, तो आप इसे सीधे उपयोग कर keyWindow में जोड़ सकते हैं addSubview:और यह तुरंत सबसे ऊपर का दृश्य होगा। मुझे यकीन नहीं है कि यह वही है जो आप हालांकि करना चाह रहे हैं। (आपके प्रश्न के आधार पर, ऐसा लगता है कि आप पहले से ही यह जानते हैं।)


111

जब भी मैं सब कुछ के ऊपर कुछ ओवरले प्रदर्शित करना चाहता हूं, मैं इसे सीधे एप्लिकेशन विंडो के शीर्ष पर जोड़ देता हूं:

[[[UIApplication sharedApplication] keyWindow] addSubview:someView]

9
केवल चित्र अभिविन्यास में काम करता है .. आप इस तरह रोटेशन आदि के बारे में परवाह है: stackoverflow.com/questions/2508630/…
hfossli

1
मैं (null)अपने iOS-8 ऐप (स्टोरीबोर्ड इश्यू?) में कोई संकेत पा रहा हूं ? धन्यवाद! (नोट: (null)दोनों समय viewDidLoadऔर viewWillAppear:समय पर लौटा है । viewDidAppear:बहुत देर हो चुकी है।
ओली

जब हम एक दृश्य नियंत्रक पेश करते हैं तो यह काम करता है ?. प्रस्तुत दृश्य नियंत्रक पर जोड़ा गया उप-भाग दिखाया जाएगा?
प्रत्यूषा तेरली

यह कीबोर्ड के ऊपर नहीं जाएगा, lastObject हालांकि करता है।
सर्प

यह रूपरेखा सभी अभिविन्यासों में काम कर सकती है। और कीबोर्ड से ऊपर जाएगा। github.com/HarrisonXi/TopmostView
हैरिसन शी

47

समस्या के दो भाग हैं: शीर्ष विंडो, शीर्ष विंडो पर शीर्ष दृश्य।

सभी मौजूदा उत्तर शीर्ष विंडो भाग से चूक गए। लेकिन [[UIApplication sharedApplication] keyWindow]शीर्ष विंडो होने की गारंटी नहीं है।

  1. शीर्ष खिड़की। यह बहुत कम संभावना है कि windowLevelएक ऐप के लिए एक ही सह-कलाकार के साथ दो खिड़कियां होंगी , इसलिए हम सभी विंडो को क्रमबद्ध करके windowLevelसबसे ऊपर प्राप्त कर सकते हैं ।

    UIWindow *topWindow = [[[UIApplication sharedApplication].windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *win1, UIWindow *win2) {
        return win1.windowLevel - win2.windowLevel;
    }] lastObject];
  2. शीर्ष विंडो पर शीर्ष दृश्य। बस पूरा होना है। जैसा कि पहले ही सवाल में बताया गया है:

    UIView *topView = [[topWindow subviews] lastObject];

5
एक बार UIAlertViews के खेल में आने के बाद इस समाधान ने मेरे लिए काम करना बंद कर दिया - वे एक पीछे छोड़ने वाली UIWindow को छोड़ने लगते हैं, इसलिए मैं वापस लौट आयाtopView = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];
Gereon

4
यदि कीबोर्ड ऊपर है तो यह काम नहीं करता है। जैसा कि वह सबसे ऊपर वाली खिड़की है
एंट्रॉपी

@Gereon, सुनिश्चित करें कि आप किसी भी UIAlertView के लिए एक मजबूत संदर्भ नहीं रख रहे हैं। यदि यह एक कमजोर संदर्भ नहीं है, तो UIAlertOverlayWindow अभी भी पदानुक्रम में होगा और कुंजी विंडो के रूप में पहचाना जाएगा, लेकिन इसमें जोड़े गए साक्षात्कार प्रदर्शित नहीं होंगे।
बीबीकॉन

iOS 8 के मामले में topWindow मान उचित नहीं है
मेहुल ठक्कर

11

वास्तव में आपके एप्लिकेशन में एक से अधिक UIWindow हो सकते हैं। उदाहरण के लिए, यदि कोई कीबोर्ड स्क्रीन पर है, तो [[UIApplication sharedApplication] windows]कम से कम दो विंडो (आपकी की-विंडो और कीबोर्ड विंडो) होगी।

इसलिए यदि आप चाहते हैं कि आपका विचार उन दोनों को प्रदर्शित करे, तो आप कुछ ऐसा करेंगे:

[[[[UIApplication sharedApplication] windows] lastObject] addSubview:view];

(मान लें कि LastObject में विंडो सबसे अधिक WindowLevel प्राथमिकता के साथ है)।


[[[अपयोग साझाकरण] विंडोज़] lastObject] मान ul 8 के मामले में उचित नहीं है
मेहुल ठक्कर

मैंने इसका उपयोग करना शुरू कर दिया, लेकिन ऐसा लगता है कि कभी-कभी कीबोर्ड विंडो मौजूद होती है, लेकिन दिखाई नहीं दे रही है, और फिर मेरा विचार बिल्कुल भी प्रदर्शित नहीं होता है!
टेराडिल

3

मैं शीर्षक के रूप में प्रश्न पर चर्चा कर रहा हूं और चर्चा नहीं। किसी भी बिंदु पर कौन सा दृश्य सबसे ऊपर दिखाई देता है?

@implementation UIView (Extra)

- (UIView *)findTopMostViewForPoint:(CGPoint)point
{
    for(int i = self.subviews.count - 1; i >= 0; i--)
    {
        UIView *subview = [self.subviews objectAtIndex:i];
        if(!subview.hidden && CGRectContainsPoint(subview.frame, point))
        {
            CGPoint pointConverted = [self convertPoint:point toView:subview];
            return [subview findTopMostViewForPoint:pointConverted];
        }
    }

    return self;
}

- (UIWindow *)topmostWindow
{
    UIWindow *topWindow = [[[UIApplication sharedApplication].windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *win1, UIWindow *win2) {
        return win1.windowLevel - win2.windowLevel;
    }] lastObject];
    return topWindow;
}

@end

रिसीवर के रूप में किसी भी UIWindow के साथ सीधे उपयोग किया जा सकता है या रिसीवर के रूप में किसी भी UIView के साथ।


topWindow iOS 8 के मामले में गलत मूल्य दे रहा है, क्या आप iOS 8 के लिए अपने जवाब को अपडेट कर सकते हैं
मेहुल ठक्कर

1
मेरे पास पता लगाने का समय नहीं है। यदि आप करते हैं तो आप इस पोस्ट को अपडेट करने के लिए स्वतंत्र हैं।
hfossli

1

यदि आप एक लोडिंग दृश्य (उदाहरण के लिए एक गतिविधि संकेतक दृश्य) जोड़ रहे हैं, तो सुनिश्चित करें कि आपके पास UIWindow वर्ग की कोई वस्तु है। यदि आप अपना लोडिंग दृश्य दिखाने से ठीक पहले एक एक्शन शीट दिखाते हैं, तो keyWindowइच्छाशक्ति होगी UIActionSheetऔर नहीं UIWindow। और चूंकि एक्शन शीट चली जाएगी, इसलिए लोडिंग दृश्य इसके साथ चला जाएगा। या कि मुझे क्या समस्या हो रही थी।

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
if (![NSStringFromClass([keyWindow class]) isEqualToString:@"UIWindow"]) {
    // find uiwindow in windows
    NSArray *windows = [UIApplication sharedApplication].windows;
    for (UIWindow *window in windows) {
        if ([NSStringFromClass([window class]) isEqualToString:@"UIWindow"]) {
            keyWindow = window;
            break;
        }
    }
}

1

यदि आपका आवेदन केवल पोर्ट्रेट ओरिएंटेशन में काम करता है, तो यह पर्याप्त है:

[[[UIApplication sharedApplication] keyWindow] addSubview:yourView]

और आपका दृश्य कीबोर्ड और स्टेटस बार पर नहीं दिखाया जाएगा।

यदि आप एक सर्वोच्च दृश्य प्राप्त करना चाहते हैं जो कीबोर्ड या स्टेटस बार पर है, या आप चाहते हैं कि शीर्ष दृश्य उपकरणों के साथ सही तरीके से घूम सके, तो कृपया इस ढांचे को आज़माएँ:

https://github.com/HarrisonXi/TopmostView

यह iOS7 / 8/9 को सपोर्ट करता है।


0

यदि आप स्क्रीन में सब कुछ के ऊपर एक दृश्य जोड़ना चाहते हैं तो बस इस कोड का उपयोग करें।

[[UIApplication sharedApplication].keyWindow addSubView: yourView];

0

इसे इस्तेमाल करे

UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject];

विंडो प्रॉपर्टी के बारे में: "इस प्रॉपर्टी में ऐप के लिए वर्तमान में मौजूद सभी विंडो के अनुरूप NSWindow ऑब्जेक्ट्स की एक सरणी होती है। सरणी में सभी ऑनस्क्रीन और ऑफस्क्रीन विंडो शामिल हैं, चाहे वे किसी भी स्थान पर दिखाई दें या नहीं। ऑर्डर की कोई गारंटी नहीं है। सरणी में खिड़कियों की। "
स्टीवन फिशर

0
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
if (![NSStringFromClass([keyWindow class]) isEqualToString:@"UIWindow"]) {

    NSArray *windows = [UIApplication sharedApplication].windows;
    for (UIWindow *window in windows) {
        if ([NSStringFromClass([window class]) isEqualToString:@"UIWindow"]) {
            keyWindow = window;
            break;
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.