Swift4中以Popover方式打开ViewController报错求助
Hey there! Let's get that popover working properly for your MoodController. Your existing code is close, but there are a few critical pieces missing that are causing the problem. Here's what you need to do:
1. Set the Popover's Source View & Rect
Popovers require a clear anchor point to know where to appear on screen. Without setting sourceView and sourceRect, you'll run into crashes on iPad (since the system can't determine the popover's origin) and unexpected full-screen behavior on iPhone.
If you're triggering the popover from a button (or any UI element), bind the popover to that element:
// Replace 'sender' with your triggering UI element (e.g., a UIButton) if let popoverPC = controller.popoverPresentationController { popoverPC.sourceView = sender popoverPC.sourceRect = sender.bounds // Optional: Control which direction the popover arrow points popoverPC.permittedArrowDirections = .any }
2. Implement the Required Delegate Method
By default, iPhones will render popovers as full-screen modals instead of floating popovers. To force the popover style across all devices, implement the adaptivePresentationStyle(for:) method from UIPopoverPresentationControllerDelegate:
// Add this extension to your presenting view controller extension YourPresentingViewController: UIPopoverPresentationControllerDelegate { func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle { // Keep the popover style instead of switching to full-screen return .none } }
3. Use Safe Optional Unwrapping
Avoid force-unwrapping popoverPresentationController with ! — this can lead to crashes if the controller isn't configured correctly. Use if let or guard let to safely access it instead.
Full Corrected Code
Here's the complete, safe version of your code (assuming you're triggering from a button):
@IBAction func showMoodPopover(_ sender: UIButton) { let storyboard = UIStoryboard(name: "Main", bundle: nil) guard let moodController = storyboard.instantiateViewController(withIdentifier: "MoodController") as? MoodController else { print("Failed to load MoodController from storyboard") return } // Set popover presentation style moodController.modalPresentationStyle = .popover // Configure popover anchor and delegate if let popoverPC = moodController.popoverPresentationController { popoverPC.delegate = self popoverPC.sourceView = sender popoverPC.sourceRect = sender.bounds popoverPC.permittedArrowDirections = .up } // Present the popover present(moodController, animated: true, completion: nil) }
Common Issues to Check
- Make sure your presenting view controller conforms to
UIPopoverPresentationControllerDelegate(the extension above takes care of this). - Double-check that
MoodControllerhas the correct storyboard identifier set in Interface Builder. - If you're not triggering from a button, adjust
sourceViewandsourceRectto point to the appropriate UI element or area on screen.
内容的提问来源于stack exchange,提问作者Alex

