runtime是不是在OC中用的比较多?runtime我确实接触的少,之前也就是在OC中交换两个方法中用到,这段时间在我们项目里看到这方面代码了,然后也遇到了一些问题,学习了,这里也记录下吧~~~
代码如下:
extension AppDelegate {
@discardableResult
func getKeyWindow() -> UIWindow {
guard let window = self.window else {
let window = UIWindow(frame: UIScreen.main.bounds)
window.backgroundColor = UIColor.white
window.makeKeyAndVisible()
self.window = window
return window
}
if !window.isKeyWindow {
window.makeKeyAndVisible()
}
return window
}
}
private var homeKey: Void?
private var navKey: Void?
private var waiterKey: Void?
private var personKey: Void?
extension UIApplication {
// 首页控制器
fileprivate(set) var homeViewController: HomeViewController? {
get {
return objc_getAssociatedObject(self, &homeKey) as? HomeViewController
}
set {
objc_setAssociatedObject(self, &homeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
// 导航控制器
var navigationController: BaseNavigationController? {
get {
return objc_getAssociatedObject(self, &navKey) as? BaseNavigationController
}
set {
objc_setAssociatedObject(self, &navKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
// 某一个控制器
var waiterHomeViewController:WaiterHomeViewController?{
get {
return objc_getAssociatedObject(self, &waiterKey) as? WaiterHomeViewController
}
set {
objc_setAssociatedObject(self, &waiterKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
// 某一个控制器
var personalCenterViewController:PersonalCenterViewController?{
get {
return objc_getAssociatedObject(self, &personKey) as? PersonalCenterViewController
}
set {
objc_setAssociatedObject(self, &personKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
// 获取首页控制器
private func getHomeViewController() -> HomeViewController {
if let home = UIApplication.shared.homeViewController {
return home
}
let home = HomeViewController()
UIApplication.shared.homeViewController = home
return home
}
// 获取window
private func getKeyWindow() -> UIWindow {
return (UIApplication.shared.delegate as! AppDelegate).getKeyWindow()
}
// 获取导航控制器
private func getNavigationController() -> BaseNavigationController {
if let nav = UIApplication.shared.navigationController {
getKeyWindow().rootViewController = nav
return nav
}
let nav = BaseNavigationController()
UIApplication.shared.navigationController = nav
getKeyWindow().rootViewController = nav
return nav
}
private func getWaiterHomeViewController() -> WaiterHomeViewController {
if let waiter = waiterHomeViewController {
return waiter
}
let vc = UIStoryboard(name: "WaiterHome", bundle: Bundle.main).instantiateInitialViewController() as! WaiterHomeViewController
waiterHomeViewController = vc
return vc
}
private func getPersonalCenterViewController() -> PersonalCenterViewController {
if let personal = personalCenterViewController {
return personal
}
let vc = PersonalCenterViewController()
personalCenterViewController = vc
return vc
}
// 跳转到首页控制器
func gotoHomeViewController(with animated: Bool = true) {
func toHome(with nav: BaseNavigationController) {
var childs = nav.children
for vc in childs.reversed() {
vc.resignFirstResponder()
vc.presentedViewController?.dismiss(animated: false, completion: nil)
}
if let home = childs.first, home.isMember(of: HomeViewController.self) {
nav.popToRootViewController(animated: animated)
}else {
childs.removeAll()
let home = getHomeViewController()
childs.append(home)
nav.setViewControllers(childs, animated: animated)
}
}
let nav = getNavigationController()
toHome(with: nav)
}
func gotoPersonalCenterViewController(with animated: Bool = true) {
let nav = getNavigationController()
if let top = nav.topViewController, top.isMember(of: PersonalCenterViewController.self) {
let childs = nav.children
for vc in childs.reversed() {
vc.resignFirstResponder()
vc.presentedViewController?.dismiss(animated: false, completion: nil)
}
return
}
let vc = getPersonalCenterViewController()
if let top = nav.topViewController, top.isMember(of: PersonalCenterViewController.self) {
nav.pushViewController(vc, animated: animated)
}else {
gotoHomeViewController(with: false)
let nav = getNavigationController()
nav.pushViewController(vc, animated: animated)
}
}
func gotoWaiterHomeViewController(with animated: Bool = true) {
let nav = getNavigationController()
if let top = nav.topViewController, top.isMember(of: WaiterHomeViewController.self) {
let childs = nav.children
for vc in childs.reversed() {
vc.resignFirstResponder()
vc.presentedViewController?.dismiss(animated: false, completion: nil)
}
return
}
let vc = getWaiterHomeViewController()
if let top = nav.topViewController, top.isMember(of: PersonalCenterViewController.self) {
if !top.isKind(of: WaiterHomeViewController.self) {
nav.pushViewController(vc, animated: animated)
}
}else {
gotoPersonalCenterViewController(with: false)
let nav = getNavigationController()
if let top = nav.topViewController, !top.isKind(of: WaiterHomeViewController.self) {
nav.pushViewController(vc, animated: animated)
}
}
}
func pop2Business() {
gotoWaiterHomeViewController(with: false)
let nav = getNavigationController()
let temp = BusinessViewController()
temp.canGoBack = false
let business = BaseNavigationController(rootViewController: temp)
nav.topViewController?.popup(controller: business, direction: .center, enableDismiss: true)
}
func gotoRootViewController() {
let root = RootViewController()
getKeyWindow().rootViewController = root
}
}
代码大概的意思代码里有注释。
我们项目里的这些需要频繁跳转的控制器就是在这里统一跳转,以前写这个代码的说是当时是为了低设备性能考虑,不频繁的创建控制器,所以创建了一个全局的控制器。
遇到的问题:
1、启动程序,不走设置UIApplication.shared.navigationController的代码时,存在代码中取UIApplication.shared.navigationController的时候不能push,因为此时UIApplication.shared.navigationController是nil。
暂时我是这么取可以的:
extension UIApplication {
var baseNavigationController: BaseNavigationController? {
if let nav = (UIApplication.shared.delegate as? AppDelegate)?.window?.rootViewController as? BaseNavigationController {
return nav
} else {
for window in UIApplication.shared.windows.reversed() {
if let nav = window.rootViewController as? BaseNavigationController {
return nav
}
}
}
return nil
}
}
2、创建这些runtime设置的全局控制器变量后需要设置一下UIApplication里的控制器,需要更新,不然会一直引用,会出现内存泄露。
暂时就遇到这些问题吧,记录一下~~大家周末快乐!!!
网友评论