我如何从自定义向上滑动菜单中显示控制器

问题描述

我正在尝试快速自定义向上滑动菜单显示控制器,但是当我从菜单中选择一个选项时,它没有显示控制器。

起初我使用苹果警报控制器,它工作正常,但我将其更改为自定义创建的菜单,该菜单从屏幕底部滑入,如下所示:

我使用以下类来构建它:

class SettingsLauncher: NSObject,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {


let blackView = UIView()
let cellHeight = CGFloat(50)
let collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero,collectionViewLayout: layout)
    cv.backgroundColor = UIColor.rgb(red: 35,green: 35,blue: 35,alpha: 1)
    return cv
}()

let settings: [Setting] = {
   return [
        Setting(name: "Profile Settings",imageName: "gear"),Setting(name: "My Store",imageName: "bag"),Setting(name: "Search User",imageName: "magnifyingglass"),Setting(name: "Cancel",imageName: "xmark")
   ]
}()

override init() {
    super.init()
    
    collectionView.dataSource = self
    collectionView.delegate = self
    
    collectionView.register(SettingsCell.self,forCellWithReuseIdentifier: reuseidentifier)
}

func showSettings() {
    
    if let window = UIApplication.shared.keyWindow {
        blackView.backgroundColor = UIColor.clear
        blackView.addGestureRecognizer(UITapGestureRecognizer(target: self,action: #selector(handledismiss)))
        
        window.addSubview(blackView)
        window.addSubview(collectionView)
        
        let height: CGFloat = CGFloat(settings.count) * cellHeight + 50
        let y = window.frame.height - height
        collectionView.frame = CGRect(x: 0,y: window.frame.height,width: window.frame.width,height: height)
        collectionView.layer.cornerRadius = 20
        
        blackView.frame = window.frame
        blackView.alpha = 0
        
        UIView.animate(withDuration: 0.5,delay: 0,usingSpringWithdamping: 1,initialSpringVeLocity: 1,options: .curveEaSEOut) {
            self.blackView.alpha = 1
            self.collectionView.frame = CGRect(x: 0,y: y,width: self.collectionView.frame.width,height: self.collectionView.frame.height)

        } completion: { (nil) in
            
        }
    }
}

@objc func handledismiss(setting: Setting) {
    
        UIView.animate(withDuration: 0.5,options: .curveEaSEOut) {
            self.blackView.alpha = 0
            if let window = UIApplication.shared.keyWindow {
                self.collectionView.frame = CGRect(x: 0,height: self.collectionView.frame.height)
            }

        } completion: { (nil) in
            let mainTab = MainTabVC()
            mainTab.presentController(setting: setting)
    }
}


//MARK: - Collection View

func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
    return settings.count
}

func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseidentifier,for: indexPath) as! SettingsCell
    
    let setting = settings[indexPath.row]
    cell.setting = setting
    
    return cell
}


func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,minimumLinespacingForSectionAt section: Int) -> CGFloat {
    return 0
}

func collectionView(_ collectionView: UICollectionView,sizeforItemAt indexPath: IndexPath) -> CGSize {
    let width = collectionView.frame.width
    print(width)
    return CGSize(width: width,height: cellHeight)
}


func collectionView(_ collectionView: UICollectionView,didSelectItemAt indexPath: IndexPath) {
    
    let setting = self.settings[indexPath.item]
    handledismiss(setting: setting)
}
}

当我选择四个项目中的一个时,菜单会被关闭,并会显示一个适当的控制器,但它不起作用。这就是我尝试这样做的方式,但我认为这是不正确的:

例如,当用户选择“搜索用户”时,它应该执行以下操作:

函数在另一个名为 MainTabVC() 的类中处理,该类是配置所有导航栏项目的地方,当它们被按下时,它调用上面的类来显示菜单

func presentController(setting: Setting) {
    if setting.name == "Search User" {
        let searchVC = SearchVC()
        let navigationController = UINavigationController(rootViewController: searchVC)
        navigationController.title = "Search User"
        self.navigationController?.present(navigationController,animated: true,completion: nil)
    } else {
        print(setting.name)
    }
}

用户选择不是“选择用户”的选项时,代码会被执行并打印出每个设置的名称,但为什么不显示控制器。

任何帮助都会有所帮助,谢谢。

enter image description here

解决方法

当你用这种方式触发动作时

let mainTab = MainTabVC()
mainTab.presentController(setting: setting)

您实际上创建了一个从未包含在任何窗口和 MainTabVC() 方案中的新 UI

您可以开始编写通信协议了。

protocol SettingsLauncherDelegate: class {
    func settingDidSelected(setting: Setting)
}

然后在SettingsLauncher

class SettingsLauncher: NSObject {
    
    // add weak delegate variable
    weak var delegate: SettingsLauncherDelegate?
    
}

func collectionView(_ collectionView: UICollectionView,didSelectItemAt indexPath: IndexPath) {
    
    let setting = self.settings[indexPath.item]
    delegate?.settingDidSelected(setting: setting)
}

然后进入你的目标 UIViewController

使您的视图控制器符合这样的协议。

class ViewController: UIViewController,SettingsLauncherDelegate{
      let settingsLauncher = SettingsLauncher()
             
      override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        settingsLauncher.delegate = self
       }

      // this will be triggered when any action is selected
      func settingDidSelected(setting: Setting) {
        print("selected setting > ",setting)
      }
}

然后将自定义 UIView 类的委托变量设置为 self

这将解决您的问题。