Swift - 将相同的导航栏项添加到每个页面

时间:2016-11-24 08:04:28

标签: ios swift

我正在尝试将相同的导航栏项添加到我的应用程序中的每个选项卡。我目前在homeController中正确设置它们,但我想将代码移动到一个单独的文件中,并在任何我想要的地方远程实现它。

例如:在导航栏的左侧添加[搜索]图标,而不必在每个swift文件中使用相同的代码。

我不知道是否应该创建枚举,协议或类。这样做的最佳方式是什么?

let menuButton = UIButton(type: UIButtonType.system)
menuButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
menuButton.addTarget(self, action: #selector(openSearch), for: .touchUpInside)
menuButton.setImage(UIImage(named: "icon_search"), for: UIControlState())
let menuBarButtonItem = UIBarButtonItem(customView: menuButton)

navigationItem.leftBarButtonItems = [menuBarButtonItem]

func openSearch() {
 // Some code
}

3 个答案:

答案 0 :(得分:10)

我建议的方法是创建一个基本视图控制器类,并使所有单独的视图控制器从此而不是直接从UIViewController开始。

虽然您可以像Umair建议的那样进行快速而又脏的扩展,但这对其他应用程序来说并不实用,而基本视图控制器允许您基本上添加功能/自定义应用程序中所有视图控制器的任何方面的外观

以下是一些示例代码:

class BaseViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let menuButton = UIButton(type: UIButtonType.system)
        menuButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
        menuButton.addTarget(self, action: #selector(openSearch), for:    .touchUpInside)
        menuButton.setImage(UIImage(named: "icon_search"), for: UIControlState())
        let menuBarButtonItem = UIBarButtonItem(customView: menuButton)

        navigationItem.leftBarButtonItems = [menuBarButtonItem
    }

    func openSearch() {

    }
}

然后,对于您应用中的所有视图控制器,只需进行声明:

class SomeRandomViewController: BaseViewController { }

修改

正如评论中正确指出的那样,您必须在每个 base 类中执行此操作。 (UIViewController,UITableViewController,UITabViewController等...)有一种方法,但它通常被认为是Objective-C运行时的黑暗艺术之一。我当然是在谈论方法调整。以下代码基本上交换了UIViewController' viewWillAppear:的实现和自定义方法。如果正确完成,这是完全安全的,下面显示了正确的实现。

extension UIViewController {
    public override class func initialize() {
        struct Static {
            static var token: dispatch_once_t = 0
        }

        // make sure this isn't a subclass
        if self !== UIViewController.self {
            return
        }

        dispatch_once(&Static.token) {
            let originalSelector = Selector("viewWillAppear:")
            let swizzledSelector = Selector("extended_viewWillAppear:")

            let originalMethod = class_getInstanceMethod(self, originalSelector)
            let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

            let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))

            if didAddMethod {
                class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
            } else {
                method_exchangeImplementations(originalMethod, swizzledMethod)
            }
        }
    }

    // MARK: - Method Swizzling

    func extended_viewWillAppear(animated: Bool) {
        self.extended_viewWillAppear(animated)

        // Call your code here that you want to run for all view controllers, table view controllers, tab view controllers etc...
    }
}

有些开发人员无法忍受上述概念,您应该意识到它可能会在未来的iOS版本中发生变化并中断。也就是说,它不会让你的应用被拒绝,因为它是一种实际的编程技术。

答案 1 :(得分:0)

您可以通过扩展UIViewController来轻松使用它

扩展UIViewController {

func setupRemainingNavItems() {
    self.navigationController?.setNavigationBarHidden(false, animated: true)
    navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
    navigationController?.navigationBar.shadowImage = UIImage()
    let titleImageView = UIImageView(image: #imageLiteral(resourceName: "trukk-icon"))
    titleImageView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
    titleImageView.contentMode = .scaleAspectFit
    titleImageView.clipsToBounds = true
    navigationItem.titleView = titleImageView

    let button = UIButton(type: .custom)
    button.setImage(UIImage (named: "Group 6"), for: .normal)
    button.frame = CGRect(x: 0.0, y: 0.0, width: 30.0, height: 30.0)
    button.addTarget(self, action: #selector(tapbutton), for: .touchUpInside)
    let barButtonItem = UIBarButtonItem(customView: button)

    self.navigationItem.leftBarButtonItem = barButtonItem
}

@objc func tapbutton(){
    self.navigationController?.popViewController(animated: true)
    print("tap")
}

}

用途:

在ViewDidLoad()中调用它

setupRemainingNavItems()

答案 2 :(得分:0)

面向未来的人

如果不是subclassinghardcoding buttons的话,这就是我的解决方法:

  1. navigation bar中的Storyboard中添加所需的按钮
  2. outlets/actions连接到您的TabBarController
  3. 假设您的流量是TabBarController --> NavigationController --> tab1/tab2/tab3的{​​{1}}中的viewDidLoad(),请添加:
TabBarController