Objective-C(五、@class,id类型,类对象构造方法,加载和初始化,description,Logging宏)——iOS开发基础


结合之前的学习笔记以及参考《Objective-C编程全解(第三版)》,对Objective-C知识点进行梳理总结。知识点一直在变,只是作为参考,以苹果官方文档为准~


五、类对象


1、类的前置声明:@class
出现下列情况(循环引用)时:

 Person.h中,包含Book对象
 #import "Book.h"
 @interface Person : NSObject
 {
     Book *_book;
 }
 @end
 Book.h中,引用Person对象
 #import "Person.h"
 @interface Book : NSObject
 {
     Person* _author;
 }
 @end

此时,编译器会报错,unknown type name ‘Book’/’Person’,这是使用@class对类作一个声明就可以,说明是一个类,_book是Book类对象,_author是Person类的对象。

@class与#import区别
(1)@class只是告诉编译器Book是一个类名,但是这个类具体有什么样的实例变量和方法无法确定。(因此如果要在源文件.m中调用方法或引用实例变量时需要在.m中import)
(2)#import是一个预处理指令,把包含的文件的全部内容插入到当前文件夹中。

@class的优点
(1)可以避免循环引用引起的嵌套包含
(2)如果一个工程中多个文件#import了同一个头文件,当头文件要改动,所有包含此文件的都需要重新进行编译,编译效率较低,而@class不需要重新编译(不是嵌套包含,为了提高编译效率也可以用)

之前#import和#include的区别已经在其他篇章中提过,为了方便,这里再次罗列~
#import与#include
(1)两者都在预处理阶段把头文件的内容插入到当前的源文件中;
(2)#include多次导入同一文件,会导致重复包含,而#import会自动判断此前文件是否被导入过,若导入则不做导入操作,确保只导入一次。

2、id类型
(1)定义

 typedef struct objc_object {
     Class isa;
 }*id;

OC中特有的数据类型,通用型(万能)指针类型,可以指向任意的OC对象;
(2)id类型可以指向任意类型的实例对象,到程序的运行期,会根据实际指向对象里面的isa指针找到所属的类,再去类中查找方法的入口地址,实现多态;
id类型
(3)id类型的变量不能使用点语法
(4)注意:id类型一般用于方法的参数类型和返回值类型,不可滥用,能确定实例对象类型的要指定其所属的类

3、构造方法:类中用来初始化对象的成员变量的对象方法
(1)Person *p = [[Person alloc] init]; 相当于
Person *p = [Person new];
alloc给此对象分配内存,类方法;
init初始化成员变量,NSObject中初始化为0,初始化失败返回nil

(2)子类重写init方法,使初始化值不为0
——>规则
a、必须调用父类init方法,初始化从父类继承过来的成员变量
b、验证父类成员是否初始化成功后,才能初始化子类新增的成员变量
c、返回经过了初始化后的当前实例对象self

 - (instancetype)init {
     self = [super init];//调用父类,有益于程序的扩展性,当父类成员发生变化时,只用在父类中修改,子类中不需要改动
     if (self != nil) {  //等价于if(self = [super init])
     _age = 10;
     }
     return self;
 }

(3)自定义构造方法
——>规则:
a、必须是对象方法
b、返回值必须是id类型
c、方法名以init开头,传参数后接With

 - (id)initWithAge:(NSInteger)age andName:(NSString *)name {
     if (self = [super init]) {
         _age = age;
     }
     return self;
 }

4、类对象的类型(本质)
(1)类就是一个对象,类型为Class,简称类对象(!!!Class跟id一样是指针类型,只是一个地址,并不需要了解实际指向的内容
(2)类名就是类对象,可直接用类对象调用类方法
(3)获取类对象的方法:

 a、类方法获取
 Class c = [Person class];
b、对象方法获取
 Person *p = [[Person alloc] init];
 Class c1 = [p1 class];
 NSLog(@"%p,%p",c,c1);地址的结果是一样的

5、类的加载和初始化过程

 + load:类对象加载后调用的方法
 当程序开始运行的时候,会加载当前项目中所有的类,加载完成后自动调用  +load方法,只调用一次。
  +initialize:类对象初始化的方法
  当程序第一次使用某个类时,会调用此方法,只调用一次

类对象加载和初始化规则:
(1)先加载父类,再加载子类(初始化也相同)
(2)都可以重写,来验证先后顺序。

6、description方法
作用:直接输出实例变量,把对象的所有成员的值一一输出(打印的时候会自动调用)
a、对象方法:- description,以%@输出一个实例对象的结果
(1)返回值类型是NSString*,把这个字符串输出到屏幕上
(2)NSObject类的此方法默认返回 <类名:实例对象的内存地址>
(3)可重写,按照一定的格式输出实例变量,方便用户查看

- (NSString *)description {
     return [NSString stringWithFormat:@"age=%li,name=%@",_age,_name];
 }

b、类方法:+ description,以%@输出一个实例对象的结果
(1)返回值类型是NSString*,返回值为类名!

 Class c1 = [Person class]; //类方法获取类对象
 NSLog(@"%@", c1);  //打印出来是Person
 或者用对象方法获取类对象

(2)可重写类方法

7、几个对于Logging有用的宏

MacroFormat SpecifierDescription
__func__%sCurrent function signature.
__LINE__%dCurrent line number in the source code line.
__FILE__%sFull path to the source code file.
__PRETTY_FUNCTION__%sLike fun,but includes verbose type information in C++ code.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值