【问题标题】:What is the best way output the name of the class who's method is being called?输出被调用方法的类的名称的最佳方法是什么?
【发布时间】:2012-02-16 12:26:20
【问题描述】:

我知道 NSStringFromClass。

我的问题与在继承树中的多个类中实现相同方法的情况有关,并且您想要调试有关它从哪个类执行的信息。

例子:

让我们有三个类: A-->B-->C ,如箭头所示继承。

如果他们每个人都有一个方法 foo(),定义:

-(void) foo
{
 // Do some work particular to the class it is in.
  .....
  //Each method ends with the debugging statement:
  NSLog("In foo of class:%$",NSClassFromString([self class]));
}

B 类的 foo 调用 [super foo] 时会出现问题。当 [super foo](即 A 类)到达 NSLog 语句时,[self class] 返回 B 类,而不是 A。

同样,如果 C 调用 [super foo],super 中的日志语句将记录类 C。

我要做的是输出正在执行其方法实现的类——所以如果B类调用[super foo],那么[A foo]中的日志语句输出A类。

简单的方法是将 NSClassFromString 替换为表示类名的硬编码字符串,但我想知道是否有更好的方法来做到这一点?

【问题讨论】:

    标签: objective-c class inheritance logging


    【解决方案1】:

    您可以使用__PRETTY_FUNCTION__ 来包含类名和方法名:

    NSLog(@"Greetings from %s", __PRETTY_FUNCTION__);
    

    我不相信只有类名有编译时宏。

    【讨论】:

      【解决方案2】:

      类可能没有宏,但 C 语言中有 __FILE____LINE__ 宏。它们扩展到当前文件和行号。您可以在 NSLog 中使用它们。我记得时使用__PRETTY_FUNCTION__,但我记得__FILE____LINE__更多。

      例子:

      NSLog( @"%s %d", __FILE__, __LINE__ );
      

      请记住,__FILE__ 不是 Objective-C 字符串。

      【讨论】:

        【解决方案3】:

        B 类的 foo 调用 [super foo] 时会出现问题。当[超 foo](即A类)到达NSLog语句,[self class]返回 B 级,而不是 A 级。

        当然。那是因为self 指向一个对象,并且该对象的类不会因为您调用超类的方法而改变。

        简单的方法是用硬编码的字符串替换 NSClassFromString 代表类名,但我想知道是否有更好的 如何做到这一点?

        正如其他人所指出的,您可以使用像__PRETTY_FUNCTION__ 这样的宏,但我认为简单明了的方法是最好的。你在写代码的时候就知道类的名字,所以可以写:

        NSLog("In foo of class: %@", @"ClassA");
        

        每个类都有自己的方法实现,因此每个类都可以在消息中打印自己的类名。当您编写要在多个函数中使用的调试宏时,__PRETTY_FUNCTION__ 之类的东西很有用。这不是这里的情况。使用显而易见的方法可以更轻松地查看正在发生的事情,这在调试期间很重要(我假设这是您在这里尝试做的事情)。

        【讨论】:

          【解决方案4】:

          我认为您必须使用class_getSuperclassclass_getInstanceMethod 向上走类层次结构,比较方法的差异。这样做以确定 objc 类,然后使用 class_getNameNSStringFromClass 获取其名称。

          这看起来像:

          NSString* MONClassNameWhichImplementsMethod(id Self, SEL cmd);
          

          - (void)method
          {
            NSLog(@"%@ - %@",
              MONGetClassWhichImplementsMethod(self, _cmd),
              NSStringFromSelector(_cmd)
            );
          }
          

          // NOT COMPILED -- FOR ILLUSTRATION ONLY
          Class MONClassWhichImplementsMethod(Class cls, SEL cmd) {
            assert(cls && cmd && "srsly?");
          
            Class super = class_getSuperclass(cls);
            Method m1 = class_getInstanceMethod(cls, cmd);
            assert(m1 && "srsly?");
          
            Method m2 = class_getInstanceMethod(super, cmd);
            if (0 == m2) {
              return cls;
            }
            else if (m1 != m2) {
              return cls;
            }
            else {
              return MONClassWhichImplementsMethod(super, cmd);
            }
          }
          
          NSString* MONClassNameWhichImplementsMethod(id Self, SEL cmd) {
            return NSStringFromClass(MONClassNameWhichImplementsMethod(Self.class, cmd));
          }
          

          如果它因深度递归而崩溃,那你就有另一个问题了。

          【讨论】:

            猜你喜欢
            • 2013-06-18
            • 1970-01-01
            • 2013-04-21
            • 2019-01-24
            • 1970-01-01
            • 2011-05-26
            • 2015-08-08
            • 2016-09-19
            • 2011-03-01
            相关资源
            最近更新 更多