swiftuikitinterface-builder

Sheets in UIKit


I'm new to UIKit. What is the correct way to make a sheet visible, using the interface builder (probably), not SwiftUI. My actual goal is to have a sheet with custom detents. I have tried to create a new storyboard file and a UIViewController, and I have set the class name in the identity inspector. I have also tried to add my UIViewController to the main storyboard. This is how I open the sheet when a button in the main view is tapped:

@IBAction func click(_ sender: UIButton) {
    let myViewController: MyViewController = .init()
    myViewController.loadViewIfNeeded()
    present(myViewController, animated: true)
}

This my view controller:

import Foundation
import UIKit

class MyViewController: UIViewController, UIViewControllerTransitioningDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
//        view.backgroundColor = .systemBackground
        modalPresentationStyle = .custom
        transitioningDelegate = self
    }
    
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        let controller: UISheetPresentationController = .init(presentedViewController: presented, presenting: presenting)
        
        let detent: UISheetPresentationController.Detent = .custom(resolver: { context in 100 })
        
        controller.detents = [detent, .medium()]
        controller.prefersGrabberVisible = true
        
        return controller
    }
}

There's a button at the top of my sheet in the interface builder, but it's not visible in the sheet. In fact, the whole sheet is transparent, and changing the color in the IB has no effect. The main view gets dimmed, I can see the grabber, and the detents are in place.

Changing the background color programmatically does work. Do I have to link the storyboard and view controller somewhere else in order to display my view, or what am I missing?


Solution

  • This has nothing to do with sheets or detentes or anything else: you simply have not understood what a storyboard is. This line

    let myViewController: MyViewController = .init()
    

    means you are not using the storyboard. Therefore nothing you do in the storyboard can possibly have any effect on the way this view controller looks. That is why changing the background color of the view controller's view works in code but not in the storyboard; the view controller and its view are created entirely in code, so they must be configured entirely in code.

    That's perfectly okay; many people prefer to work without storyboards, and storyboards do not do very much for you, if anything, that you cannot do programmatically. So if you like, stick with that.

    If you really do want to fetch the view controller from the storyboard, one way is to give the view controller in the storyboard an identifier, get a reference to the storyboard, and tell the storyboard to instantiate the view controller by identifier.

    Alternatively, you can make a presentation segue from your main view controller to the presented view controller within the storyboard, and then, in code or by responding to the tap of a button or similar in the interface, trigger the segue (this will cause the presented view controller to be instantiated and presented).