【问题标题】:Unable to print current ViewController Name using method swizzling [duplicate]无法使用方法 swizzling 打印当前 ViewController 名称 [重复]
【发布时间】:2019-09-25 14:22:14
【问题描述】:

我想打印ViewController 名称,而不是在每个ViewController 中打印屏幕名称,还有其他可能使用ViewController 扩展名打印ViewController 名称吗?或者有什么建议?

例如如果您在登录页面,它应该打印LoginViewController,如果您移动到主屏幕,它应该打印HomeViewController 我尝试了下面的代码,但它没有打印确切的类名。

extension UIViewController {
@objc dynamic func _tracked_viewWillAppear(_ animated: Bool) {

    print("ClassName@: "+String(describing: type(of: self)))
    _tracked_viewWillAppear(animated)
}

static func swizzle() {
    if self != UIViewController.self {
        return
    }
    let _: () = {
        let originalSelector =
            #selector(UIViewController.viewWillAppear(_:))
        let swizzledSelector =
            #selector(UIViewController._tracked_viewWillAppear(_:))
        let originalMethod =
            class_getInstanceMethod(self, originalSelector)
        let swizzledMethod =
            class_getInstanceMethod(self, swizzledSelector)
        method_exchangeImplementations(originalMethod!, swizzledMethod!);
    }()
}

Appdelegate.swift 文件中

func application( _ application: UIApplication, 
            didFinishLaunchingWithOptions 
            launchOptions: [UIApplication.LaunchOptionsKey: Any]?
            ) -> Bool {

               UIViewController.swizzle()

             return true
}

输出:-

ClassName@: UIInputWindowController
ClassName@: UISystemKeyboardDockController
ClassName@: UICompatibilityInputViewController
ClassName@: UICompatibilityInputViewController
ClassName@: UICompatibilityInputViewController
ClassName@: UICompatibilityInputViewController
ClassName@: UICompatibilityInputViewController
ClassName@: UISystemKeyboardDockController

但它不是打印ViewController 的名称。 谢谢。

【问题讨论】:

  • let class_name = "\(HomeViewController.classForCoder())"
  • let name = String(describing: type(of: self))
  • @AnuragSharma 它应该是“(self.classForCoder())”而不是“(HomeViewController.classForCoder())”,因为我是在 UIViewController 扩展中编写的。在这里,我正在尝试使用方法 swizzling 打印类名。
  • 这……太矫枉过正了。如果你实现了,请分享。
  • @ManuMateos 是的,我做到了,你可以在你的项目中试试这个。我上面写的代码是正确的。

标签: ios swift


【解决方案1】:

我会做类似的事情

struct StringUtils {
    static func className(_ obj: AnyObject) -> String {
        return String(describing: type(of: obj))
    }
}

然后调用如下

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        print(StringUtils.className(self))
    }

}

【讨论】:

    【解决方案2】:

    你可以使用type(of: T)方法

    print(type(of: self))
    

    游乐场示例:

    import UIKit
    
    class SomeViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            print(type(of: self))
        }
    }
    
    let vc = SomeViewController()
    vc.loadViewIfNeeded()
    

    输出: SomeViewController

    【讨论】:

    • 这里我们需要在每个类的 viewDidLoad 中写入 print(type(of:self)) 但我需要一个解决方案,比如动态打印当前可见的 VIewController 名称。
    • 有很多不同的方法可以做到这一点。创建一个执行此操作的自定义 UIViewController 并让您的所有其他人继承它。您可以创建一个自定义导航控制器来打印它设置/推送的所有类
    【解决方案3】:

    你可以自己写一个 UIViewController 子类,重写 viewDidAppear 方法,使用这段代码:

       override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            print("Shown viewcontroller " + String(describing: type(of: self)))
            // (do whatever)
        }
    

    然后,从其他类继承这个类。

    【讨论】:

    • 我们可以用 UIVieController 的扩展来打印吗?
    • 您可以从任何地方打印String(describing: type(of: self),而不仅仅是 UIViewController。这种子类化和覆盖是为了确保每个屏幕都打印消息。扩展与向类添加方法或多或少相同。您需要从某个地方调用该函数来运行该代码。
    • 如果需要,扩展 UIViewController 并将该行代码添加到新方法中,然后您可以从任何视图控制器调用该方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 1970-01-01
    • 2021-02-09
    • 2012-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多