添加多个子视图的最佳方法 UIViewControllers

Posted

技术标签:

【中文标题】添加多个子视图的最佳方法 UIViewControllers【英文标题】:Best way to add a subview more than one UIViewControllers 【发布时间】:2018-08-01 09:14:21 【问题描述】:

我正在尝试找到一种向某些 UIViewController 添加带有操作的简单 UIButton 子视图的好方法。

我认为它可以使用协议及其扩展,但扩展 does not allow @objc 方法,这意味着我无法使用 Selector 添加目标。

我创建了另一个类来解决这个@objc 问题,但我无法将视图添加为参数...

我还创建了一个 UIViewController 子类,它运行良好,但我不确定使用该子类实现大量 UIViewController 是否是个好主意。

所以问题是,将带有动作的子视图添加到多个 UIViewController 的最佳解决方案是什么?

请参阅下面的代码:

public protocol ImplementNewRightIcon 
    func setupNewBottomRightMenu()


public extension ImplementNewRightIcon where Self: UIViewController 

func setupNewBottomRightMenu() 

    let buttonwith: CGFloat = 50

    let button: UIButton = 
       let btn = UIButton()
        btn.setImage(#imageLiteral(resourceName: "icons8-plus-math-50_white"), for: .normal)
        btn.backgroundColor = .red
        btn.clipsToBounds = true
        btn.layer.cornerRadius = buttonwith * 0.5
        btn.imageEdgeInsets = UIEdgeInsetsMake(10,10,10,10)
        btn.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
        btn.layer.shadowOffset = CGSize(width: 0.0, height: 2.0)
        btn.layer.shadowOpacity = 0.5
        btn.layer.shadowRadius = 0.0
        btn.layer.masksToBounds = false
        btn.addTarget(SetupMenuLayer.sharedInstance, action: #selector(SetupMenuLayer.showMenuButtonDidTapped(SenderViewController:)), for: .touchUpInside)
        return btn;
    ()

    self.view.addSubview(button)
    button.anchor(top: nil, left: nil, bottom: self.view.bottomAnchor, right: self.view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 20, paddingRight: 20, width: buttonwith, height: buttonwith)


class SetupMenuLayer: NSObject 
static let sharedInstance = SetupMenuLayer()

@objc func showMenuButtonDidTapped(SenderViewController: UIViewController) 

    let bottomMenuView: UIView = 
        let view = UIView()
        view.backgroundColor = .red
        return view
    ()

    SenderViewController.view.addSubview(bottomMenuView)
    bottomMenuView.anchor(top: nil, left: SenderViewController.view.leftAnchor, bottom: SenderViewController.view.bottomAnchor, right: SenderViewController.view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: SenderViewController.view.frame.width, height: SenderViewController.view.frame.height / 3)


class ImplementNewRightIconView: UIViewController 

override func viewDidLoad() 
    self.setupNewRightIconBtn()


func setupNewRightIconBtn() 
    let buttonwith: CGFloat = 50

    let button: UIButton = 
        let btn = UIButton()
        btn.setImage(#imageLiteral(resourceName: "icons8-plus-math-50_white"), for: .normal)
        btn.backgroundColor = .red
        btn.clipsToBounds = true
        btn.layer.cornerRadius = buttonwith * 0.5
        btn.imageEdgeInsets = UIEdgeInsetsMake(10,10,10,10)
        btn.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
        btn.layer.shadowOffset = CGSize(width: 0.0, height: 2.0)
        btn.layer.shadowOpacity = 0.5
        btn.layer.shadowRadius = 0.0
        btn.layer.masksToBounds = false
        //it works
        btn.addTarget(self, action: #selector(showMenuButtonDidTapped), for: .touchUpInside)
        return btn;
    ()

    self.view.addSubview(button)
    button.anchor(top: nil, left: nil, bottom: self.view.bottomAnchor, right: self.view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 20, paddingRight: 20, width: buttonwith, height: buttonwith)


@objc func showMenuButtonDidTapped() 

    let bottomMenuView: UIView = 
        let view = UIView()
        view.backgroundColor = .red
        return view
    ()

    self.view.addSubview(bottomMenuView)
    bottomMenuView.anchor(top: nil, left: self.view.leftAnchor, bottom: self.view.bottomAnchor, right: self.view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: self.view.frame.width, height: self.view.frame.height / 3)


【问题讨论】:

你试过用'@objc extension'代替'@objc func'吗? 是的,我做到了,'@objc' 只能应用于类的扩展 【参考方案1】:

您可以对 UIButton 进行扩展并添加具有以下语义的方法:

func addTergetClosure(didTouch: () -> Void)

didTouch 将在 touchUpInside 事件中被调用,详细说明here 如何实现。 接下来,您只需要像您一样为 UIViewController 创建一个带有 Self 约束的协议,这会将您的按钮添加为子视图。而且我会将按钮属性添加为协议部分,因为您可能需要在这些视图控制器中的某处访问它,而不仅仅是添加将在 touchUpInside 上调用的按钮和闭包。

所以它会是这样的:

protocol MyProtocol  
   var button: UIButton  get set 
   func setButton()


extension MyProtocol where Self: UIViewController 
   func setButton()  ... 

如果您的按钮在 ViewControllers 上看起来很相似,那么我建议您将该逻辑与 UIButton 扩展分开,并使用静态字段返回 UIButton 以及您需要的样式。在提供的解决方案中,您只需在 ViewController 中设置按钮,如

class MyController: UIViewController, MyProtocol 
   var button = UIButton.shadowed


extension UIButton 
    static let shadowed: UIButton =  ... 

【讨论】:

【参考方案2】:

如果你想在同一个ViewController中添加多个UIViewControllers作为子视图,那么你肯定需要使用Container View。

【讨论】:

【参考方案3】:

如果您希望多个视图控制器具有共享功能,或者在您的特定情况下始终将此按钮添加到同一个位置,您应该创建一个基本视图控制器供它们继承。

class ViewControllerWithMenu: UIViewController 
    override func viewDidLoad() 
        super.viewDidLoad()
        setupNewBottomRightMenu()   
    

    func setupNewBottomRightMenu() 

    let buttonwith: CGFloat = 50

    let button: UIButton = 
       let btn = UIButton()
        btn.setImage(#imageLiteral(resourceName: "icons8-plus-math-50_white"), for: .normal)
        btn.backgroundColor = .red
        btn.clipsToBounds = true
        btn.layer.cornerRadius = buttonwith * 0.5
        btn.imageEdgeInsets = UIEdgeInsetsMake(10,10,10,10)
        btn.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
        btn.layer.shadowOffset = CGSize(width: 0.0, height: 2.0)
        btn.layer.shadowOpacity = 0.5
        btn.layer.shadowRadius = 0.0
        btn.layer.masksToBounds = false
        btn.addTarget(SetupMenuLayer.sharedInstance, action: #selector(SetupMenuLayer.showMenuButtonDidTapped(SenderViewController:)), for: .touchUpInside)
             return btn;
        ()

        self.view.addSubview(button)
        button.anchor(top: nil, left: nil, bottom: self.view.bottomAnchor, right: 
        self.view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 20, paddingRight: 20, width: buttonwith, height: buttonwith)

    


现在你不需要在每个视图控制器中调用任何东西,只需从这个视图控制器扩展而不是 UIViewController

【讨论】:

以上是关于添加多个子视图的最佳方法 UIViewControllers的主要内容,如果未能解决你的问题,请参考以下文章

向 UIScrollView 添加多个子视图

我们可以在 iOS 中同时向一个窗口添加多个子视图吗?

给 UIView 添加多个子层只会显示一个

Oracle Sql:如何在 sql 中添加多个子总计?

delphi 一个窗体添加多组单选框问题

iOS 分类:按顺序添加视图