简体   繁体   中英

presenting a modal in viewdidappear with swift

I'm new to swift and ios programming in general. I'm trying to display a modal view when my app first loads which it does. The problem I'm running into is that my modal keeps appearing over and over and over. Not sure where I'm going wrong.

BONUS QUESTION: Ultimately I'd like this to only happen the first time the user opens the app.

class ViewController: UIViewController {

    var introModalDidDisplay = false

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        showIntroModal()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func showIntroModal() {
        if (!introModalDidDisplay) {
            println(introModalDidDisplay)
            introModalDidDisplay = true
            let intro = self.storyboard?.instantiateViewControllerWithIdentifier("introModal") as IntroModalViewController
            intro.modalPresentationStyle = UIModalPresentationStyle.FormSheet
            self.presentViewController(intro, animated: true, completion: nil)
        }
    }
}

Found it. My "intro" class was extending ViewController rather than UIViewController ...apparently that's bad. Thanks for the help! Sorry for the wild goose chase.

When you close the modal view you show your ViewController view again, firing viewDidAppear once more and entering an infinite loop of showing your modal view, since the first view is always "appearing"

I'd suggest doing this in viewDidLoad , as the view is supposed to load only once. Try and experiment with these events and see when they are fired.

As for firing only once I'd suggest setting a flag in localStorage (plist) indicating whether it's the first time the user opens the app or not. For example set a flag in the first view's viewDidLoad and if that flag is false show your modal view and set the flag to true.

Here's a question about writing in plists in Swift: Save Data to .plist File in Swift

A couple of observations:

  1. Are you saying that you're seeing this appear again and again while you're using the app? That would suggest that you have multiple instances of this view controller instantiated. For example, you might be doing a segue back to this view controller (which will create new instance) rather than unwinding/popping/dismissing back to it (which will return to the previous instance).

    I'd suggest you have a breakpoint or logging statement in viewDidLoad and confirm that you see this once and only once. If you're seeing it multiple times, that means that you have some circular reference amongst your storyboard scenes (and, BTW, you are abandoning memory, a type of leak).

  2. To handle this only presenting itself once between uses of the app, you need to save this introModalDidDisplay in some form of persistent storage. Often NSUserDefaults is used for this. For example, define introModalDidDisplay to look up the status in the standard user defaults:

     var introModalDidDisplay = NSUserDefaults.standardUserDefaults().boolForKey("introModalDidDisplay") 

    Then your showIntroModal can update this setting in the user defaults:

     func showIntroModal() { if !introModalDidDisplay { introModalDidDisplay = true NSUserDefaults.standardUserDefaults().setBool(true, forKey: "introModalDidDisplay") NSUserDefaults.standardUserDefaults().synchronize() let intro = self.storyboard?.instantiateViewControllerWithIdentifier("introModal") as IntroModalViewController intro.modalPresentationStyle = UIModalPresentationStyle.FormSheet self.presentViewController(intro, animated: true, completion: nil) } } 

    Clearly, you can use whatever persistent storage technique you want (plist, archive, user defaults, Core Data, SQLite), but the idea is the same: Retrieve the status from persistent storage and once the intro screen has been presented, update that persistent storage accordingly.

    By the way, by looking this up in persistent storage, we also fix the symptom of the problem I discussed in point #1. But you really want to fix the root cause of that first point, too, because otherwise you'll be leaking memory (if, of course, you're really instantiating multiple copies of the ViewController class).


By the way, looking ahead to the future, rather than storing just a boolean, I might suggest storing a version number identifier, too. That way, when you release version 2.0 of the app, you'll be able to decide whether the v1.0 users might see the updated intro screen again (or perhaps a custom one that focuses on what's new).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM