首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iOS 8+ UIActionSheet 棄用:改用 UIAlertController 實現 ActionSheet 風格

     編輯:程式設計綜合問答

直接原因

iOS 8 起 UIActionSheet 正式棄用 (Deprecated)。 若在 iOS 8+ 繼續使用 UIActionSheet 添加子視圖 (如 UIPickerView),視圖層級結構改變導致自定義內容**完全不顯示** (僅剩空白底框)。

遷移方案:UIAlertController (PreferredStyle = .ActionSheet)

UIAlertController 統一了 Alert 和 ActionSheet,且**不支援直接添加自定義子視圖** (如 addSubview(pickerView))。需改用原生輸入方式或自定義 Container View Controller。

方案一:原生替代 (適用於簡單選單、文字輸入)

// 1. 文字選單
let alert = UIAlertController(title: "選擇城市", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "台北", style: .default) { _ in /* 處理 */ })
alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: nil))

// iPad 必須設定 popoverPresentationController 防崩潰
if let popover = alert.popoverPresentationController {
    popover.sourceView = self.view
    popover.sourceRect = sender.frame // 或 view.bounds
}
present(alert, animated: true)

方案二:自定義 Container View Controller (完美承載 UIPickerView/任何複雜視圖)

這是**官方推薦**的替代 UIActionSheet + addSubview 的標準做法。

class PickerActionSheetController: UIViewController {
    let pickerView = UIPickerView()
    var onSelect: ((Int) -> Void)?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        pickerView.dataSource = self
        pickerView.delegate = self
        view.addSubview(pickerView)
        // Auto Layout 约束 pickerView 底部、左右、高度固定
        pickerView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            pickerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            pickerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            pickerView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            pickerView.heightAnchor.constraint(equalToConstant: 216)
        ])
        
        // 頂部工具列 (完成/取消按鈕)
        let toolbar = UIToolbar()
        toolbar.items = [
            UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
            UIBarButtonItem(title: "完成", style: .done, target: self, action: #selector(doneTapped))
        ]
        view.addSubview(toolbar)
        toolbar.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            toolbar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            toolbar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            toolbar.bottomAnchor.constraint(equalTo: pickerView.topAnchor),
            toolbar.heightAnchor.constraint(equalToConstant: 44)
        ])
    }
    
    @objc func doneTapped() {
        let row = pickerView.selectedRow(inComponent: 0)
        onSelect?(row)
        dismiss(animated: true)
    }
}

// 使用時:
let pickerVC = PickerActionSheetController()
pickerVC.modalPresentationStyle = .actionSheet // iOS 13+ 自動呈現為底部彈出
pickerVC.onSelect = { row in print("選中第 \(row) 行") }
present(pickerVC, animated: true)

// iPad 適配 (同 UIAlertController)
if let popover = pickerVC.popoverPresentationController {
    popover.sourceView = view
    popover.sourceRect = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
    popover.permittedArrowDirections = []
}

方案三:第三方成熟庫 (開發效率最高)

  • ActionSheetPicker-3.0 : 專為 ActionSheet 風格 Picker 封裝,一行代碼調用。
  • FSCalendar : 如果是選日期,這是業界標準。
  • SwiftEntryKit / PopupDialog : 高度可定制的彈窗框架。

總結

棄用 UIActionSheet + addSubview(picker) 這套舊範式。
- 簡單選單 → UIAlertController(style: .actionSheet)。
- 複雜自定義視圖 (Picker、表單、列表) → **自定義 UIViewController + modalPresentationStyle = .actionSheet (iOS 13+) 或 .overCurrentContext/.custom (舊版) + 轉場動畫**。
- 圖省事 → 接入成熟第三方庫。
這樣在 iOS 8 到 iOS 17+ 所有版本都能完美、穩定運行。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved