美文网首页
iOS之id和NSObject *的区别

iOS之id和NSObject *的区别

作者: 无极战思 | 来源:发表于2020-10-16 20:32 被阅读0次

1.idobjc.h中定义

  typedef struct objc_class *Class;
  typedef struct objc_object {
  Class isa;
  } *id;

从上面可以看出,id本质是struct objc_object结构体指针,可以指向任何OC对象。
注意:这里说的是指向OC对象,像int、NSInteger这些基本数据类型可以的,将id指向int会报错

image.png

OC中的基类除了NSObject之外,还有一个NSProxy虚类。因此,id相比NSObject *指向的对象范围要更广

2.id动态数据类型,而NSObject *静态数据类型,默认情况下所有的数据类型都是静态

  • id类型的实例在编译阶段不会做类型检查,会在运行时确定,而类NSObject的实例在编译期要做编译检查,保证指针指向是其NSObject类或其子类,当然,实例的具体类型也要在运行时才能确定,这也就是iOS三大特性之一的多肽

  • 静态类型编译时就知道变量的类型,编译时就知道变量的类型,在编译的时候就可以访问对象的属性方法,如果访问了不属于静态类型的属性方法,那么编译器就会报错,而动态数据类型编译的时候并不知道变量的真实类型,只有在运行时的时候才知道它的真实类型,因此编译时候如果访问了不属于动态类型的属性方法,编译器不会报错,导致运行时的错误,这也是动态数据类型弊端
    举例如下:

    #import <Foundation/Foundation.h>
    NS_ASSUME_NONNULL_BEGIN
    @interface People : NSObject
    -(void)eatFood;
    @end
    NS_ASSUME_NONNULL_END
    #import "People.h"
    @implementation People
    -(void)eatFood
     {
     NSLog(@"eatFood");
     }
     @end
    
    
    
    #import "ViewController.h"
    #import "People.h"
    @interface ViewController ()
    
    @end
    @implementation ViewController
    
    -(void)drinkWater
    {
    NSLog(@"drinkWater");
    }
    - (void)viewDidLoad {
    [super viewDidLoad];
    id test = [People new];
    [test drinkWater];
    // Do any additional setup after loading the view.
    }
    @end
    

从上面代码我们不难看出,drinkWater方法并不是id指针指向对象的方法,调用了不是自己的方法,但是编译没有报错,只有运行时才报错了。

相关文章

网友评论

      本文标题:iOS之id和NSObject *的区别

      本文链接:https://www.haomeiwen.com/subject/cuctmktx.html