【问题标题】:iOS Class MethodiOS 类方法
【发布时间】:2017-02-08 12:57:16
【问题描述】:
@interface TestObj :NSObject
@property(copy, nonatomic)NSString *name;
@end
@implementation TestObj
- (void)testName{

  NSLog(@"name:%@",self.name);

}
@end 

@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {

  [super viewDidLoad];

  id tclass =[TestObj class];

  void * vid = &tclass;

  [(__bridge id)vid testName];

}
@end

日志:

 name: <ViewController: 0x7ff3584b6580>

我的理解是vid是一个指向TestObj类对象地址的指针,那为什么vid可以直接发给testName实例方法呢?

另外,为什么testName方法调用NSLog会输出&lt;ViewController: 0x7ff3584b6580&gt;而不是nil?

谢谢。

【问题讨论】:

  • 可以在指向类的指针上调用实例方法真的很奇怪。看看如果将testName 更改为类方法而不是实例方法会发生什么。
  • -[TestObj testName]:无法识别的选择器发送到实例

标签: ios objective-c runtime


【解决方案1】:

我认为您基本上很幸运,您没有因该代码而崩溃。

首先,类方法以+ 而不是- 开头——所以这是您正在实现的实例方法。

@interface TestObj :NSObject
@property(copy, nonatomic)NSString *name;
@end
@implementation TestObj
+ (void)testName{
NSLog(@"name:%@", @"TestObj"); // cannot reference ivars or properties in class method
}
@end
...
Class classObject = [TestObj class];
[classObject testName];

您不想使用指向类对象(或实例)的指针。 Objective-C 运行时将取消引用你给它的指针,以便找到“isa”实例变量,这将是它所属的类。类对象的“isa”是“元类”,它包含类方法的列表,这就是类方法查找的工作方式。在您的示例中,它将取消引用指针并找到 TestObj 类,这意味着它认为它正在调用 TestObj 实例上的一个方法,而实际上它不是——您没有分配一个,但它实际上只是一个垃圾指针。但是,它仍然会(完全幸运)进入您的实例方法实现,但“self”并不是真正有效的实例。但是,无论值是什么,它都恰好响应一个 -name 方法并返回具有该值的 NSString 或 UIViewController 实例本身。或者,它可能试图根据垃圾指针来延迟实例变量,并偶然得到一个指向 ViewController 实例的指针。我认为这会尝试调用 -name 方法。

无论如何,tl;dr - 你的代码是完全错误的(不要使用 & 类或实例的指针),你很幸运你没有崩溃。 (bridge id) cast 隐藏了试图帮助您的警告。

【讨论】:

    猜你喜欢
    • 2017-05-01
    • 1970-01-01
    • 2012-10-26
    • 2016-01-15
    • 2018-06-22
    • 1970-01-01
    • 2016-06-14
    • 2011-03-17
    • 2013-01-12
    相关资源
    最近更新 更多