输出正在调用方法的类名称的最佳方法是什么?

时间:2012-01-23 03:09:56

标签: objective-c class inheritance logging

我知道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中的log语句将记录C类。

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

简单的方法是用表示类名的硬编码字符串替换NSClassFromString,但我想知道是否有更好的方法来执行此操作?

4 个答案:

答案 0 :(得分:2)

您可以使用__PRETTY_FUNCTION__同时包含类和方法名称:

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

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

答案 1 :(得分:1)

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

示例:

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

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

答案 2 :(得分:1)

  

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

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

  

简单的方法是用硬编码字符串替换NSClassFromString   代表班级名称,但我想知道是否有更好的   这样做的方法?

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

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

每个类都有自己的方法实现,因此每个类都可以在消息中打印自己的类名。当您编写将要在多个函数中使用的调试宏时,类似__PRETTY_FUNCTION__的内容非常有用。情况并非如此。使用这种明显的方法可以更容易地看到正在发生的事情,这在调试期间很重要(我假设你在这里尝试做的事情)。

答案 3 :(得分:0)

我认为你必须使用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));
}

如果它从深度递归中爆炸,你还有另外一个问题。