6

I am not getting what's wrong with my code. I am simply displaying an alert with "Ok" button and when user click on "Ok", then alert should go. But its not getting disappeared. Using Swift3 for programming. Is viewDidAppear() right place to put this code? Or am I doing something wrong?

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let alertController = UIAlertController(title: "Wrong Item", message: "Could not find details of an item.", preferredStyle: .alert)          
    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    present(alertController, animated: true, completion: nil)  
}

UPDATE: When I put the same code in other controller, it worked. In original controller, in viewDidLoad(), I have an Async call like below. Is this problem because of that?

DispatchQueue.global(qos: .background).async {
    self.getDetails(onCompletion: {(json: JSON) in

    let dict = self.convertToDictionary(text: json.stringValue)

        DispatchQueue.main.async {

            self.activityIndicator.stopAnimating()
            UIApplication.shared.endIgnoringInteractionEvents()

            //Other UI update operation

        }
    })
}    

I also override viewWillDisappear() and viewWillAppear(), just to set Title of Screen.

Ashwini Chougale
  • 1,093
  • 10
  • 26
NGR
  • 1,230
  • 2
  • 15
  • 44

5 Answers5

5

are you calling UIApplication.shared.beginIgnoringInteractionEvents() anywhere bro?? if yes that is your problem.

Irshad Mohamed
  • 2,129
  • 1
  • 18
  • 19
  • Yes. I have it in that controller to make sure user can't click on UI while its loading. But I have UIApplication.shared.endIgnoringInteractionEvents() too to end it inside Async call in viewDidLoad(). And the alert code is in viewDidAppear() – NGR Aug 13 '17 at 06:36
  • I also think this is the problem, see that you are using a queue in the background, so it has a low priority to complete. This will also complement the fact that the alert can be displayed while your activity indicator is on the screen. – Claudio Castro Aug 15 '17 at 16:31
  • My suggestion, (I'm assuming that you really want to read your json only in load and want the alert to be triggered whenever you display the screen, even if it is in a return) put the call to alert in a specific function and make the Call it in viewdidload after the endignoring and in the viewdidappear. Create a variable that will serve as a flag to control if the alert was called by the viewdidload and thus should not be called by the viewdidappear. – Claudio Castro Aug 15 '17 at 16:31
1

If we create a new "single view" project For the the following two ways of presenting the alert we get the following behaviors

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

        let alertController = UIAlertController(title: "Wrong Item", message: "Could not find details of an item.", preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(alertController, animated: true, completion: nil)
    }

In the console you will see

2017-08-15 16:27:35.871 test[66719:7754741] Warning: Attempt to present on whose view is not in the window hierarchy!

and no alert on the UI.

and for:

   override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        let alertController = UIAlertController(title: "Wrong Item", message: "Could not find details of an item.", preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(alertController, animated: true, completion: nil)
    }

every thing works as expected.

So yes, view did appear is the place.

About viewDidLoad() and viewDidAppear(_:)

From the looks of it the problem lies with beginIgnoringInteractionEvents

If you are putting your alert on viewDidAppear you should see it but if you don't see it, please note the following:

Even if you put this piece of code in viewdidload

        DispatchQueue.main.async {

            self.activityIndicator.stopAnimating()
            UIApplication.shared.endIgnoringInteractionEvents()

            //Other UI update operation

        }

it may get executed later (depends on when the parsing finishes) than the call of viewDidAppear and this is because:

DispatchQueue.global(qos: .background).async

Did you check this reason?

Durdu
  • 4,649
  • 2
  • 27
  • 47
1

I add below code in viewDidAppear() just before Alert code and it started working. I kept below code at both location, i.e in Async call as well as in viewDidAppear()

self.activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
Ashwini Chougale
  • 1,093
  • 10
  • 26
NGR
  • 1,230
  • 2
  • 15
  • 44
0

endIgnoringInteractionEvents() is in an async method when you click OK this method haven't been called. so you can't dismiss alert.

Zhang
  • 394
  • 2
  • 11
-1

Your code looks fine, and viewDidAppear is fine as the your view controller will be loaded properly and it won't break the main thread to show you the alert. There's should be some other problem with your code, (bug of) Xcode, or derived data problem.

You can do a couple of things to see the actual problem:

  1. Clean build
  2. Delete file from Derived Data
  3. Delete App from Simulator
  4. Clean once again
  5. Restart Xcode and Simulator
  6. Rebuild to see if it works or not.
Hemang
  • 26,840
  • 19
  • 119
  • 186
  • While this helps, it's not really an answer and is probably better off as a comment on the questions helping the OP narrow down the issue. – Abizern Aug 06 '17 at 15:28
  • 2
    @Abizern, you are right, but how can I write the whole answer in a properly formatted comment? I have read so many other answers still contains only a single line suggesting any of the above thing and people accepts or upvote them as well. Here, I received a downvote for that reason. – Hemang Aug 07 '17 at 04:24
  • Couldn't get alert after moving it inside Async call – NGR Aug 07 '17 at 17:37