Why is it bad practice to have a viewController dismiss itself?

Using delegation is the best and more flexible way to dismiss view controller.
The purpose of it is that in some future or in some other place in your code you may reuse this VC, but due of some reasons you may not present it modal, but push into navigation stack. So your ModalVC does not know how it was presented, but delegate does.
In this case you can have 2 places in your code

  1. You present it modal and delegate calls

    [self dismiss...]
    
  2. You push it into navigation stack and delegate calls

    [self.navigationController popView...]
    
  3. You add it as a child VC and delegate calls

    [someParentVC removeChild..] 
    

    or any other appropriate workflow to remove it.