ऐप को बैकग्राउंड से खोलने पर ViewDidAppear नहीं कहा जाता है


175

मेरे पास एक व्यू कंट्रोलर है जिसमें मेरा मान 0 (लेबल) है और जब मैं खोलता हूं कि दूसरे से व्यू कंट्रोलर को ViewControllerमैंने viewDidAppearलेबल पर मान 20 सेट करने के लिए सेट किया है। यह ठीक काम करता है, लेकिन जब मैं अपना ऐप बंद करता हूं और फिर से मैं अपना ऐप खोलता हूं, लेकिन मान नहीं बदलता है viewDidLoad, viewDidAppearऔर viewWillAppearकुछ भी नहीं मिलता है। जब मैं अपना ऐप खोलूंगा तो मैं कैसे कॉल कर सकता हूं क्या मुझे कुछ करना है applicationDidBecomeActive?


जब अनुप्रयोग सक्रिय हो जाता है और पर्यवेक्षक और अद्यतन मूल्यों के रूप में अपने दृश्य नियंत्रक को जोड़ने के लिए आप एक स्थानीय अधिसूचना पोस्ट कर सकते हैं।
आदिल सूमो

जवाबों:


314

घटनाओं के सटीक अनुक्रम के बारे में उत्सुक, मैंने एक ऐप निम्नानुसार लिख दिया: (@Zohaib, आप अपने प्रश्न का उत्तर देने के लिए नीचे NSNotificationCenter कोड का उपयोग कर सकते हैं)।

// AppDelegate.m

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    NSLog(@"app will enter foreground");
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    NSLog(@"app did become active");
}

// ViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"view did load");

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}

- (void)appDidBecomeActive:(NSNotification *)notification {
    NSLog(@"did become active notification");
}

- (void)appWillEnterForeground:(NSNotification *)notification {
    NSLog(@"will enter foreground notification");
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"view will appear");
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"view did appear");
}

लॉन्च के समय, आउटपुट इस तरह दिखता है:

2013-04-07 09:31:06.505 myapp[15459:11303] view did load
2013-04-07 09:31:06.507 myapp[15459:11303] view will appear
2013-04-07 09:31:06.511 myapp[15459:11303] app did become active
2013-04-07 09:31:06.512 myapp[15459:11303] did become active notification
2013-04-07 09:31:06.517 myapp[15459:11303] view did appear

पृष्ठभूमि दर्ज करें फिर अग्रभूमि पुन: दर्ज करें:

2013-04-07 09:32:05.923 myapp[15459:11303] app will enter foreground
2013-04-07 09:32:05.924 myapp[15459:11303] will enter foreground notification
2013-04-07 09:32:05.925 myapp[15459:11303] app did become active
2013-04-07 09:32:05.926 myapp[15459:11303] did become active notification

1
दान्ह, आपने यूआईएप्लिसिएशन वीलएप्टरफॉरग्राउंडनोटिफिकेशन को एपिडीडाइन्टरफॉरग्राउंड में मैप किया। क्या यह भ्रामक नहीं है? सूचना "होगा" और "किया"। क्या वह जानबूझकर था?
लुबीलुक

@Lubiluk - जानबूझकर नहीं। मैं संपादित करूँगा। अच्छी पकड़।
दांह

4
यह बहुत उपयोगी उत्तर था। मैंने यहां इसका एक स्विफ्ट संस्करण बनाया ।
सुरगाछ

पृष्ठभूमि मोड का सही प्रदर्शन!
मार्सेलो डॉस सैंटोस

जब आप होम बटन पर डबल टैप करते हैं और ऐप को बंद करते हैं तो घटनाओं का क्रम क्या होता है?
अमजद हुसैनी

134

उद्देश्य-सी का उपयोग करना

तुम एक रजिस्टर चाहिए UIApplicationWillEnterForegroundNotificationअपने में ViewControllerकी viewDidLoadविधि और जब भी एप्लिकेशन पृष्ठभूमि से वापस आता है आप जो कुछ भी अधिसूचना लिए पंजीकृत विधि में क्या करना चाहते कर सकते हैं। ViewController'एस viewWillAppear या viewDidAppear जब एप्लिकेशन को अग्रभूमि करने के लिए पृष्ठभूमि से वापस आता है बुलाया नहीं किया जाएगा।

-(void)viewDidLoad{

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doYourStuff)

  name:UIApplicationWillEnterForegroundNotification object:nil];
}

-(void)doYourStuff{

   // do whatever you want to do when app comes back from background.
}

जिस अधिसूचना के लिए आप पंजीकृत हैं, उसे रद्द करना न भूलें।

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

ध्यान दें कि यदि आप अपना पंजीकरण करते viewControllerहैं UIApplicationDidBecomeActiveNotificationतो आपका तरीका हर बार आपके ऐप के सक्रिय होने के बाद कॉल किया जाएगा, viewControllerइस अधिसूचना के लिए पंजीकरण करने की अनुशंसा नहीं की जाती है ।

स्विफ्ट का उपयोग करना

पर्यवेक्षक जोड़ने के लिए आप निम्नलिखित कोड का उपयोग कर सकते हैं

 override func viewDidLoad() {
    super.viewDidLoad()

     NotificationCenter.default.addObserver(self, selector: "doYourStuff", name: UIApplication.willEnterForegroundNotification, object: nil)
 }

 func doYourStuff(){
     // your code
 }

पर्यवेक्षक को हटाने के लिए आप स्विफ्ट के डिनिट फ़ंक्शन का उपयोग कर सकते हैं।

deinit {
    NotificationCenter.default.removeObserver(self)
}

4
हाँ यह है :) कभी-कभी उत्तर ढूंढना मुश्किल होता है :)
nsgulliver

@nsgulliver क्या मुझे मैन्युअल रूप से अधिसूचना को अपंजीकृत करना है - (शून्य) डीललोक {[[NSNotificationCenter defaultCenter] removeObserver: self]; }। क्या ऐप मेरे लिए ऐसा करेगा?
ios

43

स्विफ्ट 3.0 ++ वर्जन

viewDidLoadपृष्ठभूमि कार्रवाई से खोले गए इसे सुनने के लिए, अपने अधिसूचना केंद्र में पंजीकरण करें

NotificationCenter.default.addObserver(self, selector:#selector(doSomething), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
        

फिर इस फ़ंक्शन को जोड़ें और आवश्यक कार्रवाई करें

func doSomething(){
    //...
}

जब आपका व्यू कंट्रोलर नष्ट हो जाए तो नोटिफिकेशन ऑब्जर्वर को साफ करने के लिए अंत में इस फ़ंक्शन को जोड़ें।

deinit {
    NotificationCenter.default.removeObserver(self)
}

वीसी +1 के अंदर की सूचना को संभालने के लिए आसान और सीधे आगे का समाधान
मो

विश्वास नहीं कर सकता यह अच्छा जवाब इतने सारे समान / डुप्लिकेट SO प्रश्नों में छूट गया है।
ह्यूगो अल्लेक्सिस कार्डोना

11

स्विफ्ट 4.2। संस्करण

viewDidLoadजब एप्लिकेशन बैकग्राउंड से वापस आए तो नोटिफिकेशनकेंटर से रजिस्टर करें

NotificationCenter.default.addObserver(self, selector: #selector(doSomething), name: UIApplication.willEnterForegroundNotification, object: nil)

उस विधि को लागू करें जिसे बुलाया जाना चाहिए।

@objc private func doSomething() {
    // Do whatever you want, for example update your view.
}

एक बार ViewControllerनष्ट होने के बाद आप पर्यवेक्षक को हटा सकते हैं । यह केवल iOS9 और macOS 10.11 के नीचे आवश्यक है

deinit {
    NotificationCenter.default.removeObserver(self)
}

1
FYI करें मुझे पूरा यकीन है कि आपको इन दिनों प्रेक्षकों को दूर करने की ज़रूरत नहीं है ...
Fattie

3

UIApplicationWillEnterForegroundNotificationनोटिफिकेशन के लिए बस आपका व्यू कंट्रोलर रजिस्टर होना चाहिए और उसी के अनुसार प्रतिक्रिया दें।


मैं ऐसा कैसे करूंगा? मैंने applicationDidBecomeActive में अपना व्यूकंट्रोलर बुलाया है लेकिन। यह देखने को ओवरलैप करता है या ऐसा करने के लिए इसका जुर्माना?
ज़ोहैब

2
ApplicationDidBecomeActive (जो कि वैसे भी गलत है क्योंकि इसे कई बार कहा जाता है) में अपने व्यू कॉंट्रोलर को कॉल न करें। नोटिफिकेशन के लिए अपने viewDidLoadlike @nsgulliver में रजिस्टर करें । आप अपने लेबल को वांछित मान के साथ सेट करने के लिए viewDidAppearभी कहेंगे doYourStuff
andreagiavatto

3

मुझे लगता है कि UIApplicationWillEnterForegroundNotification के लिए पंजीकरण करना जोखिम भरा है क्योंकि आप उस अधिसूचना पर प्रतिक्रिया देने वाले एक से अधिक नियंत्रक के साथ समाप्त हो सकते हैं। कुछ भी नहीं है कि अधिसूचना प्राप्त होने पर ये नियंत्रक अभी भी दिखाई दे रहे हैं।

यहाँ मैं क्या कर रहा हूँ: मैं अनुप्रयोग के प्रतिनिधि didBecomeActive विधि से सीधे सक्रिय नियंत्रक पर viewDidAppear को मजबूर करता हूं:

नीचे दिए गए कोड जोड़ें - (void)applicationDidBecomeActive:(UIApplication *)application

UIViewController *activeController = window.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
    activeController = [(UINavigationController*)window.rootViewController topViewController];
}
[activeController viewDidAppear:NO];

7
यह गारंटी देता है कि नियंत्रक अपंजीकृत (जैसा कि यह होना चाहिए) के लिए UIApplicationWillEnterForegroundNotification के बजाय डीलडॉक में देखें। ViewDidAppear को कॉल करना स्पष्ट रूप से मेरे लिए हैक की तरह दिखता है, यह शब्दार्थ (व्यक्तिगत दृश्य) को तोड़ता है और लोगों को (अनुभव से) भ्रमित कर सकता है।
जोकिम

3

AppDelegate applicationWillEnterForeground में इसे जोड़ने का प्रयास करें।

func applicationWillEnterForeground(_ application: UIApplication) {        
    // makes viewWillAppear run
    self.window?.rootViewController?.beginAppearanceTransition(true, animated: false)
    self.window?.rootViewController?.endAppearanceTransition()
}

2

Apple के प्रलेखन के अनुसार:

(void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated;

विवरण:
एक बच्चे नियंत्रक को बताता है कि इसका स्वरूप बदलने वाला है। यदि आप एक कस्टम कंटेनर नियंत्रक लागू कर रहे हैं, तो बच्चे को यह बताने के लिए इस पद्धति का उपयोग करें कि उसके विचार प्रकट या गायब होने वाले हैंआह्वान मत करो viewWillAppear:, viewWillDisappear:, viewDidAppear:, या viewDidDisappear:सीधे

(void)endAppearanceTransition;

विवरण:

एक बच्चे नियंत्रक को बताता है कि इसका स्वरूप बदल गया है। यदि आप एक कस्टम कंटेनर नियंत्रक लागू कर रहे हैं, तो इस विधि का उपयोग बच्चे को यह बताने के लिए करें कि दृश्य संक्रमण पूर्ण है।

नमूना कोड:

(void)applicationDidEnterBackground:(UIApplication *)application
{

    [self.window.rootViewController beginAppearanceTransition: NO animated: NO];  // I commented this line

    [self.window.rootViewController endAppearanceTransition]; // I commented this line

}

प्रश्न: मैंने कैसे तय किया?

उत्तर : मुझे आवेदन में लाइनों का यह टुकड़ा मिला। इस लाइन ने मेरे ऐप को किसी भी ViewWillAppear नोटिफिकेशन को पुनः प्राप्त नहीं किया। जब मैंने इन पंक्तियों पर टिप्पणी की तो यह ठीक काम कर रहा है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.