一、点语法本质
“点语法”本质是“方法调用”当使用“点语法”时,编译器会自动展开称相应的方法id类型的对象不能用 点语法1//方法调用2Student *stu =[[Student alloc] init];3[stu setAge:10];4intage =[stu age];5//-----------------------------我是华丽分割线-----------------------------6//点语法7stu.age =10;8intage = stu.age;
二、成员变量的作用域
@public: 在任何地方都能直接访问对象的成员变量@PRivate: 只能在当前类的对象方法中直接访问 ( @implementation 中默认是 @private )@protected : 可以在当前类及其字累的对象方法中直接访问 (默认就是 @protected )@package: 只要处在同一个框架中,就能直接访问对象的成员变量@interface和@implementation中不能声明同名的成员变量没有@interface,只有@implementation,也可以开发同一个类
三、@property 和 @synthesize 、setter 和 getter 及使用细节
@property 用在 @interface 中,用来自动生成 setter 和 getter 的声明@synthesize 永在 @implementation 中,用来生成 setter 和 getter 的实现@synthesize 细节:1> @synthesizeage = _age;(setter 和 getter 实现中会访问成员变量 _age,如果成员变量 _age 不存在,就会自动生成一个 @private 的成员变量 _age )2> @synthesizeage;(setter 和 getter 实现中会访问成员变量 age,如果成员变量 age 不存在,就会自动生成一个 @private 的成员变量 age)3> 若手动实现了setter方法,编译器就只会自动生成getter方法自从 Xcode4.4 后,@property就独揽了 @synthesize 的功能。也就是说,@property 可以同时生成setter和getter的声明和实现。默认情况下,setter 和 getter 方法中的实现,会访问下划线 _ 开头的成员变量1//--[interface.h]---Xcode4.2之前的语法---------------我是华丽分割线--------2@propertyintage;//@property3//--[interface.h]--------⬆️等价于⬇️--------4- (void)setAge;5- (int)age;67//--[implementation.m]-------------------------------我是华丽分割线--------8@synthesizeintage = _age;//@synthesize9//--[implementation.m]---⬆️等价于⬇️--------10- (void)setAge {11_age =age;12}13- (int)age {14return_age;15}16//--[implementation.m]-------------------------------我是华丽分割线--------17@synthesizeintage;//@synthesize18//--[implementation.m]---⬆️等价于⬇️--------19- (void)setAge {20_age =age;21}22- (int)age {23returnage;24}2526//--[interface.h]---Xcode4.4之后有了以下新语法-------我是华丽分割线-------27@propertyintage;//@property28//--[interface.h]---------⬆️等价于⬇️-------29@interfaceStudent:NSObject{30int_age;31}32- (void)setAge;33- (int)age;34//--[implementation.m]---------------------35- (void)setAge {36_age =age;37}38- (int)age {39return_age;40}
四、id
是万能指针,能指向任何对象,相当于NSObject *,id后面不要加上*调用一个不存在的方法,编译器会马上报错id是一个结构体,OC 对象本身是一个结构体1typedefstructobjc_object {2Classisa;//每个对象都有一个isa,且isa始终指向当前类本身3} *id;//id 定义为一个结构指针
五、构造方法(基本概念、重写init方法、init方法的执行过程、自定义)
完整地创建一个可用的对象:1> 分配存储空间+alloc,2> 初始化- init(+ new方法连续完成 1>、2> 步骤)基本概念:用来初始化对象的方法,是一个对象方法,-号开头,init 方法就是构造方法重写init方法:一定要调用回 super 的 init 方法。重写目的:为了让对象创建出来,就使成员变量具有固定的值1//----Student.m-------------2- (id)init {3if(self= [superinit])//调用回super的init方法,返回对象self,即isa为Student对象4{//初始化成功5_age =10;6}7returnself;8}
1//------NSObject------------2- (id)init {3isa=[selfclass];4returnslef;5}
init方法的执行过程:先初始化父类,再初始化子类。自定义:规范:1>一定是对象方法,一定以-开头,2>返回值一般为id类型,3>方法名一般以init开头初始化的好习惯:初始化成员变量在其所在类实现中进行(优点:去耦合。即当父类改变成员变量名称,就不用改子类的代码)
六、更改Xcode模版(main.m、注释)
main.m:如 Macapplication的终端项目:进入/Users/jackieyi/Library/Developer/Xcode/Templates/Project Templates/Application/Command Line Tool.xctemplate/Templateinfo.plist,按需要修改这个plist文件即可。注释:如 Mac Application的终端项目:进入/Users/JackieYip/Library/Deverloper/Xcode/Templates/File Templates/Cocoa/Objective-C class.xctemplate/NSObject/___FILEBASENAME___.m,或按需要选对应文件进行修改即可。
七、分类(基本使用、使用注意、给NSString增加类方法及扩充对象方法)
作用:在不改变原来类内容的基础上,可以为类增加一些方法注意:1> 只能增加方法,无法增加成员变量,但在分类的方法中可以访问原类的成员变量2> 分类可以重新实现原来类中的方法,但是会覆盖原来的方法,会导致原来的方法无法再使用3> 方法调用的优先级:高|分类(最后参与编译的分类优先)->原类->父类|低编译顺序的查看:项目-TARGETS - Builde Phases - Complie Sources,由上往下顺序编译(全为 .m 文件,.h 文件不参与编译)
八、类的深入研究(本质、类对象的使用、类的加载和初始化)
本质:我们知道:每个对象都有类型。而类本身也是一个对象,简称“类对象”,“类对象”的类型为Class类型(Class包含*)。由“类对象”创建的对象称为“实例对象”。“类对象”默认只有一份被加载到内存中,“实例对象”可以有多份被加载到内存中(不同的“实例对象”,其isa始终指向其同一“类对象”)。1Student *stu =[[Student alloc] init];2Class stu1 = [stuclass];//利用Class创建Student类对象,[stu class]是获取内存中的类对象3Class stu2 = [Studentclass];//stu1的地址等于stu2的地址,都是stu的地址
使用:“类对象”可以调用“类方法”加载:属于运行时机制。当程序启动的时候,就会加载一次项目中所有的类和分类(无论有无使用类)。类加载完毕之后就会调用+ load方法,只调用一次(先加载 父类 ,再加载 子类,最后加载 分类 )1+ (void)load {2//程序一启动,所有的类都调用这个加载方法3}
初始化:属于运行时机制。当第一次使用类的时候,就会调用一次+ initialize方法(先初始化 父类 ,再初始化 子类 ,如果有 分类 ,只会初始化 分类 ) 1+ (void)initialize {2//第一次使用类的时候([[类 alloc]init]),就会调用一次这个方法。我们可以在这里监听类何时被使用3}
九、description方法
默认情况下,利用NSLog和 %@ 输出 类对象 的时候,结果是:<类名:内存地址>每次调用NSLog(@"%@",“实例对象”) 的时候,会默认调用“实例对象”的- description方法,- description 方法的返回值为 (NSString *),默认返回的是"类名+内存地址"可以重写- description方法输出所有 成员变量1- (NSSting *)description {2//NSLog(@"%@",self);//这行代码会引发死循环3return[NSString stringWithFormat:@"age=%d, name=%@", _age, _name];4}
每次调用 NSLog(@"%@",“类对象”) 的时候,会默认调用“类对象”的+ description方法,+ description 方法的返回值为 (NSString *),默认返回的是"类名"+ description也可以被重写
十、NSLog输出补充
1intmain() {2NSLog(@"%d",__LINE__);//输出当前行号(即 2 )3//NSLog(@"%s",__FILE__);//NSLog输出 C 语言字符串的时候,不能有中文4printf(@"%s\n",__FILE__);//输出源文件的名称(含路径)5NSLog(@"%s\n",__func__);//输出当前函数名(即 main )6}
十一、SEL(基本用法及其他使用)
属于运行时机制。一个SEL代表一个方法,对应方法地址对象调用 方法 时:1> 先把 方法 包装成SEL类型的数据,2> 根据SEL数据找到对应的 方法地址,3> 根据 方法地址 调用对应的方法1intmain() {2Student *stu =[[Student alloc] init];3[stu test];4[stu performSelector:@selector(test)];//间接调用test方法,@selector(test)就是一个SEL类型5[stu performSelector:@selector(test1:) withObject:@"123"];//间接调用test:方法,@selector(test:)就是一个SEL类型6}
1NSString *name =@"test";2SEL s = NSSelectorFromSrting(name)//将test方法包装成SEL数据3[stu performSelector:s];
每个方法里面都有一个SEL类型数据的_cmd,_cmd代表当前方法。给对象传递消息,其实就是给对象传递SEL数据。SEL不能直接打印,只能转成字符串进行打印。1- (void)test {2NSString *str =NSStingWithSelector(_cmd);3NSLog(@"调用了test方法---%@",str);//显示:调用了test方法---test4}