কোনও অ্যাপ্লিকেশন ব্যাকগ্রাউন্ড থেকে ফিরে আসার পরে কেন ভিউওয়াল অ্যাপ্লਅਰ কল হবে না?


279

আমি একটি অ্যাপ্লিকেশন লিখছি এবং যদি ফোনে কথা বলার সময় ব্যবহারকারী অ্যাপটি দেখছে তবে আমার দৃষ্টিভঙ্গিটি পরিবর্তন করা দরকার।

আমি নিম্নলিখিত পদ্ধতিটি প্রয়োগ করেছি:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"viewWillAppear:");
    _sv.frame = CGRectMake(0.0, 0.0, 320.0, self.view.bounds.size.height);
}

অ্যাপটি ফোরগ্রাউন্ডে ফিরে আসার সময় এটি কল করা হচ্ছে না।

আমি জানি যে আমি বাস্তবায়ন করতে পারি:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarFrameChanged:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];

তবে আমি এটি করতে চাই না। আমি বরং আমার সমস্ত লেআউট তথ্য ভিউ উইলএপিয়ার: পদ্ধতিতে রেখেছি এবং এটি সমস্ত সম্ভাব্য পরিস্থিতি পরিচালনা করতে দেয়।

এমনকি আমি ভিউওয়েলএপিয়ারকে কল করার চেষ্টা করেছি: অ্যাপ্লিকেশন উইলএন্টারফোরগ্রাউন্ড থেকে :, তবে আমি ঠিক করতে পারি না যে সেই সময়ে বর্তমান ভিউ কন্ট্রোলার কোনটি।

কেউ কি এটিকে মোকাবেলা করার সঠিক উপায় জানেন? আমি নিশ্চিত যে আমি একটি সুস্পষ্ট সমাধান মিস করছি।


1
applicationWillEnterForeground:আপনার অ্যাপ্লিকেশনটি কখন সক্রিয় স্থানে পুনরায় প্রবেশ করেছে তা নির্ধারণ করতে আপনার ব্যবহার করা উচিত ।
sudo rm -rf

আমি বলেছিলাম যে আমি আমার প্রশ্নে এটি চেষ্টা করছিলাম। উপরে উল্লেখ করুন। অ্যাপের প্রতিনিধিটির মধ্য থেকে বর্তমান ভিউ কন্ট্রোলারটি কোন তা নির্ধারণের জন্য আপনি কোনও উপায় সরবরাহ করতে পারেন?
ফিলিপ ওয়ালটন

আপনি আপনার প্রয়োজনের উপর নির্ভর করে isMemberOfClassবা ব্যবহার করতে পারেন isKindOfClass
sudo rm -rf

@ সুডো আরএম-আরএফ তখন কীভাবে কাজ করবে? তিনি কি কিসআইন্ডঅফক্লাস কল করতে যাচ্ছেন?
আকুলাস

@ ককুলাস: মঙ্গলতা জানেন, আমি কেবল তার প্রশ্নের উত্তর দেওয়ার চেষ্টা করছিলাম। নিশ্চিতভাবেই এটি করার আপনার উপায় হ'ল উপায়।
sudo rm -rf

উত্তর:


202

viewWillAppearআপনার নিজের অ্যাপ্লিকেশনটিতে যা চলছে তার প্রসঙ্গে পদ্ধতিটি নেওয়া উচিত এবং আপনি যখন অন্য অ্যাপ্লিকেশন থেকে ফিরে যান তখন আপনার অ্যাপ্লিকেশনটি অগ্রভাগে স্থাপন করা হয় না।

অন্য কথায়, যদি কেউ অন্য অ্যাপ্লিকেশনটির দিকে নজর দেয় বা ফোন কল নেয়, তবে আপনার অ্যাপ্লিকেশনটিতে ফিরে যায় যা পূর্বের পটভূমিতে ছিল, আপনার ইউআইভিউ কনট্রোলার যা আপনার অ্যাপ্লিকেশনটি রেখে যাওয়ার আগেই দৃশ্যমান ছিল তাই বলার অপেক্ষা রাখে না - যতদূর এটি সম্পর্কিত, এটি কখনও অদৃশ্য হয়ে যায় এবং এটি এখনও দৃশ্যমান - এবং তাই viewWillAppearবলা হয় না।

আমি viewWillAppearনিজেকে কল করার বিরুদ্ধে প্রস্তাব দিচ্ছি - এর একটি নির্দিষ্ট অর্থ রয়েছে যা আপনার হ্রাস করা উচিত নয়! একই প্রভাব অর্জন করতে আপনি করতে পারেন এমন একটি রিফ্যাক্টরিং নিম্নরূপ হতে পারে:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self doMyLayoutStuff:self];
}

- (void)doMyLayoutStuff:(id)sender {
    // stuff
}

তারপরে আপনি doMyLayoutStuffউপযুক্ত বিজ্ঞপ্তি থেকে ট্রিগারও করুন:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doMyLayoutStuff:) name:UIApplicationDidChangeStatusBarFrameNotification object:self];

উপায়টির বাইরে 'বর্তমান' ইউআইভিউউকন্ট্রোলার কোন তা বলার উপায় নেই। তবে আপনি তার আশেপাশের উপায়গুলি সন্ধান করতে পারেন, যেমন কোনও ইউআইভিউকন্ট্রোলার কখন এতে উপস্থাপিত হবে তা সন্ধানের জন্য ইউআইএনএভিগেশন কন্ট্রোলারের প্রতিনিধি পদ্ধতি রয়েছে। উপস্থাপিত সর্বশেষ ইউআইভিউউকন্ট্রোলারটিকে ট্র্যাক করতে আপনি এই জাতীয় জিনিস ব্যবহার করতে পারেন।

হালনাগাদ

আপনি যদি বিভিন্ন বিটগুলিতে যথাযথ অটোরিসাইজিং মাস্কগুলি সহ ইউআইগুলি আউটআউট করেন, কখনও কখনও আপনার এমনকি আপনার ইউআই থেকে বেরিয়ে আসা 'ম্যানুয়াল' নিয়েও ডিল করার প্রয়োজন হয় না - এটি কেবলমাত্র ...


101
এই সমাধানের জন্য ধন্যবাদ। আমি আসলে ইউআইএ অ্যাপ্লিকেশনডিডবেকোম্যাকটিভনোটিকেশনের জন্য পর্যবেক্ষক যুক্ত করি এবং এটি খুব ভাল কাজ করে।
ওয়েন লিউ

2
এটি অবশ্যই সঠিক উত্তর। লক্ষণীয়, তবে, "বর্তমান 'ইউআইভিউউকন্ট্রোলার কোনটি তা বলার উপায় বক্সের বাইরে নেই" এর প্রতিক্রিয়ায়, আমি বিশ্বাস করি যে self.navigationController.topViewControllerকার্যকরভাবে এটি সরবরাহ করে, বা কমপক্ষে স্ট্যাকের শীর্ষে থাকা একটি, যা হবে বর্তমান কোডটি যদি কোনও ভিউ কনটোলারে মূল থ্রেডে গুলি চালাচ্ছে। (ভুল হতে পারে, এটির সাথে খুব বেশি খেলা হয়নি, তবে কাজ করে বলে মনে হচ্ছে))
ম্যাথু ফ্রেডরিক

appDelegate.rootViewControllerখুব কার্যকর হবে, তবে এটি আবার ফিরে আসতে পারে UINavigationControllerএবং তারপরে আপনার .topViewControllerম্যাথফেড্রেডিকের কথামতো দরকার হবে need
স্যামসন

7
ইউআইএএপ্লিকেশনডিডবিকম অ্যাক্টিভনোটিকেশন ভুল (সমস্ত লোক এটি উত্সাহিত করেও)। অ্যাপ্লিকেশন শুরুতে (এবং কেবলমাত্র অ্যাপ্লিকেশন শুরুতে!) এই বিজ্ঞপ্তিটি অন্যরকম বলা হয় - এটি দেখার জন্য উইলওয়েল অ্যাপয়ার ছাড়াও বলা হয়, সুতরাং এই উত্তরটির সাথে আপনি এটি দুটিবার কল করতে পারবেন। অ্যাপল এ অধিকারটি অর্জন করা অযথা জটিল করে তুলেছে - ডক্সগুলি এখনও অনুপস্থিত (2013 সালের হিসাবে!)।
অ্যাডাম

1
আমি যে সমাধানটি নিয়ে এসেছি তা হ'ল স্ট্যাটিক ভেরিয়েবল ('স্ট্যাটিক BOOL এন্টারব্যাকগ্রাউন্ড;') এর সাথে ক্লাস ব্যবহার করা; তারপরে আমি ক্লাস মেথডস সেটার এবং গেটার যুক্ত করি। অ্যাপ্লিকেশনডেন্টারব্যাকগ্রাউন্ডে, আমি ভ্যারিয়েবলটি সত্যে সেট করে দিয়েছি। তারপরে অ্যাপ্লিকেশনডিডেকম্যাক্টিভিতে আমি স্ট্যাটিক বুলটি পরীক্ষা করি , এবং যদি এটি সত্য হয় তবে আমি "doMyLayoutStuff" করব এবং ভেরিয়েবলটিকে 'NO' এ পুনরায় সেট করব This এটি প্রতিরোধ করে: অ্যাপ্লিকেশনডবিকোম্যাকটিভ সংঘর্ষের সাথে ভিউউইল অ্যাপ্লিকেশনটি মেমরির চাপের কারণে বন্ধ হয়ে গেলে অ্যাপ্লিকেশনটি ব্যাকগ্রাউন্ড থেকে প্রবেশ করেছে বলে মনে করে না।
ভিজমার্টিন

196

দ্রুতগতি

সংক্ষিপ্ত উত্তর

NotificationCenterপরিবর্তে একটি পর্যবেক্ষক ব্যবহার করুন viewWillAppear

override func viewDidLoad() {
    super.viewDidLoad()

    // set observer for UIApplication.willEnterForegroundNotification
    NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)

}

// my selector that was defined above
@objc func willEnterForeground() {
    // do stuff
}

দীর্ঘ উত্তর

কোনও অ্যাপ্লিকেশন কখন পটভূমি থেকে ফিরে আসে তা অনুসন্ধান করার জন্য, NotificationCenterবরং কোনও পর্যবেক্ষক ব্যবহার করুন viewWillAppear। এখানে একটি নমুনা প্রকল্প যা দেখায় যে কখন কোন ঘটনাগুলি ঘটে। (এটি এই উদ্দেশ্য-সি উত্তরের একটি অভিযোজন ))

import UIKit
class ViewController: UIViewController {

    // MARK: - Overrides

    override func viewDidLoad() {
        super.viewDidLoad()
        print("view did load")

        // add notification observers
        NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)

    }

    override func viewWillAppear(_ animated: Bool) {
        print("view will appear")
    }

    override func viewDidAppear(_ animated: Bool) {
        print("view did appear")
    }

    // MARK: - Notification oberserver methods

    @objc func didBecomeActive() {
        print("did become active")
    }

    @objc func willEnterForeground() {
        print("will enter foreground")
    }

}

অ্যাপ্লিকেশন শুরু করার পরে, আউটপুট ক্রমটি হ'ল:

view did load
view will appear
did become active
view did appear

হোম বোতামটি চাপ দেওয়ার পরে অ্যাপ্লিকেশনটিকে অগ্রভাগে ফিরিয়ে আনার পরে আউটপুট ক্রমটি হ'ল:

will enter foreground
did become active 

সুতরাং আপনি যদি প্রথমে ব্যবহার করার চেষ্টা করছেন viewWillAppearতবে UIApplication.willEnterForegroundNotificationসম্ভবত আপনি যা চান তা সম্ভবত।

বিঃদ্রঃ

আইওএস 9 এবং তার পরেও আপনার পর্যবেক্ষককে অপসারণ করার দরকার নেই। ডকুমেন্টেশন পদ বলে:

যদি আপনার অ্যাপ্লিকেশনটি আইওএস 9.0 এবং তারপরে বা ম্যাকোস 10.11 এবং তার পরে লক্ষ্য করে তবে আপনাকে তার deallocপদ্ধতিতে কোনও পর্যবেক্ষককে নিবন্ধভুক্ত করার দরকার নেই ।


6
দ্রুত 4.2 এ বিজ্ঞপ্তির নাম এখন ইউআইএপ্লিকেশন। উইলইন্টারফোরগ্রাউন্ড নোটিকেশন এবং ইউআইএপ্লিকেশন.ডিডবেকোম অ্যাক্টিভনোটিকেশন
হর্ডারহ

140

viewDidLoad:কোনও পদ্ধতিতে কল করতে আপনার ভিউকন্ট্রোলারের পদ্ধতিতে বিজ্ঞপ্তি কেন্দ্রটি ব্যবহার করুন এবং সেখান থেকে আপনার viewWillAppear:পদ্ধতিতে আপনার যা করা উচিত ছিল তা করুন । viewWillAppear:সরাসরি কল করা ভাল বিকল্প নয়।

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

    [[NSNotificationCenter defaultCenter] addObserver:self 
        selector:@selector(applicationIsActive:) 
        name:UIApplicationDidBecomeActiveNotification 
        object:nil];

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

- (void)applicationIsActive:(NSNotification *)notification {
    NSLog(@"Application Did Become Active");
}

- (void)applicationEnteredForeground:(NSNotification *)notification {
    NSLog(@"Application Entered Foreground");
}

9
deallocতখন পদ্ধতিতে পর্যবেক্ষককে অপসারণ করা ভাল ধারণা হতে পারে ।
আনকাইনু

2
viewDidLoad না শ্রেষ্ট পদ্ধতি viewDidUnload পর্যবেক্ষক হিসাবে স্ব যোগ করতে যদি তাই হয়, অপসারণ পর্যবেক্ষক
Injectios

নিজেকে পর্যবেক্ষক যুক্ত করার সর্বোত্তম পদ্ধতি কোনটি?
পাইটর ওয়াসেলিউইচ

ভিউ কন্ট্রোলার কেবলমাত্র একটি বিজ্ঞপ্তির জন্য পর্যবেক্ষণ করতে পারে না, যেমন, ইউআইএপ্লিকেশন উইলইন্টারফোরগ্রাউন্ডনোটিকেশন। দুজনের কথা শুনবে কেন?
জুলকরনাইন শাহ

34

viewWillAppear:animated:, আমার মতে আইওএস এসডিকে অন্যতম বিভ্রান্তিমূলক পদ্ধতি, এ জাতীয় পরিস্থিতিতে কখনই আবেদন করা হয় না, যেমন অ্যাপ্লিকেশন স্যুইচিং। এই পদ্ধতিটি কেবলমাত্র নিয়ামকের দর্শন এবং অ্যাপ্লিকেশনটির উইন্ডোর মধ্যে সম্পর্ক অনুসারে চাওয়া হয় , যেমন বার্তাটি কোনও ভিউ কন্ট্রোলারের কাছে কেবল তখনই প্রদর্শিত হয় যদি তার দৃষ্টিভঙ্গি অ্যাপ্লিকেশনটির উইন্ডোতে প্রদর্শিত হয়, পর্দায় নয়।

যখন আপনার অ্যাপ্লিকেশনটি পটভূমিতে যায়, স্পষ্টতই অ্যাপ্লিকেশন উইন্ডোটির শীর্ষতম দৃশ্যগুলি ব্যবহারকারীর কাছে আর দৃশ্যমান হয় না। আপনার অ্যাপ্লিকেশন উইন্ডোটির দৃষ্টিকোণে তবে এগুলি এখনও শীর্ষস্থানীয় দর্শন এবং তাই সেগুলি উইন্ডো থেকে অদৃশ্য হয়নি। পরিবর্তে, অ্যাপ্লিকেশন উইন্ডো অদৃশ্য হয়ে যাওয়ার কারণে এই মতামতগুলি অদৃশ্য হয়ে গেল। উইন্ডো থেকে অদৃশ্য হয়ে যাওয়ার কারণে তারা অদৃশ্য হয়নি ।

সুতরাং, যখন ব্যবহারকারী আপনার অ্যাপ্লিকেশনটিতে ফিরে আসে, তখন তারা অবশ্যই পর্দায় উপস্থিত হবে বলে মনে হয়, কারণ উইন্ডোটি আবার প্রদর্শিত হয় appears তবে উইন্ডোর দৃষ্টিকোণ থেকে তারা মোটেই অদৃশ্য হয়নি। সুতরাং ভিউ কন্ট্রোলাররা viewWillAppear:animatedবার্তাটি কখনই পায় না ।


2
অতিরিক্তভাবে, -ভিউউইলডিস্পায়ার: অ্যানিমেটেড: অ্যাপ্লিকেশন থেকে প্রস্থান করার সময় রাজ্য সংরক্ষণের জন্য এটি একটি সুবিধাজনক জায়গা হিসাবে ব্যবহৃত হত। অ্যাপটিকে ব্যাকগ্রাউন্ড করার সময় এটি বলা হয় না, এবং ব্যাকগ্রাউন্ড অ্যাপটি কোনও সতর্কতা ছাড়াই হত্যা করা যেতে পারে।
টিসি।

6
আরেকটি সত্যিই খারাপ নামকরণ পদ্ধতি ভিউডিডঅনলোড। আপনি ভাবেন যে এটি ভিডিডিএলডের বিপরীত ছিল, তবে না; এটি তখনই বলা হয় যখন কম স্মৃতি পরিস্থিতি দেখা দেয় যার ফলে দর্শনটি আনলোড করা হত এবং প্রতিবার দৃশ্যটি ডেললকের সময়ে আসলে লোড করা হয় না।
আকুলাস

আমি @ ককুলাসের সাথে একেবারে একমত ভিউউইল অ্যাপয়ার এর অজুহাত রয়েছে কারণ (সাজানো) মাল্টিটাস্কিং ছিল না তবে ভিউডিডঅনলোড অবশ্যই আরও ভাল নাম রাখতে পারে।
এমএইচসি 12'11

আইওএস 7-এ অ্যাপ্লিকেশনটি ব্যাকগ্রাউন্ড করা অবস্থায় আমার জন্য ভিডিডিডিস্পিয়ার আইএস কল করা হয়। আমি কি একটি নিশ্চিতকরণ পেতে পারি?
মাইক কোগান

4

সুইফট 4.2 / 5

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground),
                                           name: Notification.Name.UIApplicationWillEnterForeground,
                                           object: nil)
}

@objc func willEnterForeground() {
   // do what's needed
}

3

এটি যতটা সম্ভব সহজ করার চেষ্টা করে নীচের কোডটি দেখুন:

- (void)viewDidLoad
{
   [self appWillEnterForeground]; //register For Application Will enterForeground
}


- (id)appWillEnterForeground{ //Application will enter foreground.

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(allFunctions)
                                                 name:UIApplicationWillEnterForegroundNotification
                                               object:nil];
    return self;
}


-(void) allFunctions{ //call any functions that need to be run when application will enter foreground 
    NSLog(@"calling all functions...application just came back from foreground");


}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.