#pragma mark - Day06_01_点语法 1.点语法是一个编译器特性 编译器在编译的时候,会把点语法转换成对应的getter和setter 如果是赋值(写在等号的左边),调用setter 如果是取值(写在等号的右边),调用getter 点语法的本质还是getter和setter,而不是直接访问成员变量
2.注意点 1.在定义getter和setter的时候,要慎用点语法,否则可能会造成死循环 记住一句话:在getter和setter当中,直接访问成员变量(比如_age),不要使用其他手段 如果一个函数或者方法自己调用自己, 递归,递归必须要有一个出口,防止死循环 2.如果没有给一个成员变量封装getter和setter,那么就不能使用点语法 3.在给成员变量封装setter和getter的时候,一定要注意命名规范,否则无法使用点语法
@interface HMPerson: NSObject { int _age; } - (void)setAge:(int)age; - (int)age;
@end
HMPerson *person = [HMPerson new]; int a = [person age]; person.age = 10; int a = person.age;
// 不使用点语法,给变量做自加操作,需要三步 int a = [person age]; a++; [person setAge:a];
// 使用点语法做自加操作 person.age++;
person.age = person.age + 1;
#pragma mark - Day06_02_@property的使用 Xcode4.3之前 Xcode是一个IDE,集成的软件开发工具,肯定是包含了编译器
1.@property是一个编译器特性 作用:自动生成成员变量的getter和setter的声明 是写在@interface中的
2.使用规范 @property 成员变量类型 去掉下划线的成员变量名
3.内部原理: 1.生成setter方法声明 2.生成getter方法声明
4.注意: 1.@property声明的类型一定要和成员变量类型一致 2.@property声明的名称一定要符合规范,成员变量名去掉下划线,只有这样生成的getter和setter方法声明才符合规范 3.@property可以批量声明类型相同的成员变量
#pragma mark - Day06_03_@synthesize的使用 1.@synthesize是一个编译器特性 作用:自动生成成员变量的getter和setter的实现 是写在@implementation中的
2.使用规范 @synthesize 对应的@property的名称
3.内部原理 1.在@implementation的大括号中,生成一个和@property同名的成员变量,这是一个真正私有的成员变量,没有使用_开头 2.实现setter方法,在方法内部,直接给给它自己生成的成员变量赋值 3.实现getter方法,在方法内部,直接返回它自己生成成员变量
#pragma mark - Day06_04_@synthesize的使用注意
1.因为@synthesize会自动在@implementation生成和@property同名的成员变量,所以我们如果没有在@interface中手动定义成员变量,也可以正常使用 2.如果不想让@synthesize自动生成成员变量,而是使用自己定义的成员变量,这个时候可以单独指定 1.在@interface中自己声明成员变量 2.在@synthesize后面指定需要使用的变量.格式: @synthesize 对应的@property的名称 = 成员变量
3.注意: 1.@synthesize后面的名称一定是在@interface中声明的@property名称 2.@synthesize可以自动的生成setter和getter的实现,但是在实现中没有逻辑判断,只是单纯的赋值.如果你需要在赋值的时候进行判断,那么重写@synthesize自动生成的方法即可 3.@synthesize可以批量声明不同类型的变量
举例: @interface HMPerson : NSObject { NSString *_name; } @property NSString *name; @end
@implementation HMPerson @synthesize name = _name; @end
4. 编译器特性: 1.点语法:简化getter和setter的调用 2.@property:简化getter和setter的声明 3.@synthesize:简化getter和setter的实现
以上所有内容,都是Xcode4.3之前的特性
在Xcode4.4之后,不需要使用@synthesize了,有一种更加简单的形式
#pragma mark - Day06_05_@property的增强使用 在Xcode4.4之后,苹果对@property进行了增强 1.在@implementation中生成一个和@property类型相同,在@property名字前添加下划线的私有成员变量 2.自动生成该变量的getter和setter的声明 3.自动生成该变量的getter和setter的实现,但是在方法的实现内部没有逻辑判断,如果想进行判断,自己重写即可. 4.@property只能写在@interface和@end之间
#pragma mark - Day06_06_使用@property增强注意 1.使用@property生成的成员变量和@property中声明的类型一致 2.@property可以批量声明类型相同的变量,但是不推荐使用,建议大家分来写,这是一个规范 3.@property自动生成的setter和getter实现是没有逻辑判断的,如果想进行判断,自己重写即可 1.如果只重写setter,那么会自动生成私有的成员变量以及getter 2.如果只重写getter,那么会自动生成私有成员变量以及setter 3.如果同时重写了getter和setter,那么不会自动生成成员变量
就业班的课程里面,@property,根据某些需求,重写set方法,或者重写get方法
4.以后开发中 1.使用@property自动声明成员变量以及对应的getter和setter的声明和实现 2.使用点语法快速调用getter和setter
"补充 5.@property只有写在@interface和@end之间的时候,才会做三件事情 @interface @end @implementation @end
OC中还有其它特殊的语法:分类\协议,当在这些地方使用@property的时候,会做不同的事情
6.@property中可以通过参数说明生成成员变量的特性 参数有三种类型: 1.线程相关 nonatomic 线程不安全的 atomic 线程安全的 2.内存管理相关,说明使用什么样的内存策略 assign retain copy strong weak 3.说明读写特性 readonly
@property (nonatomic, copy) NSString *name; @property (nonatomic, copy, readonly) NSString *name;
@property NSString *name;
点招面试的时候, 1.是什么 2.有什么作用 3.怎么使用 4.注意点
#pragma mark - Day06_07_任意的指针可以指向任意的对象 1.OC是一门弱语法的语言 OC是一门动态的语言,只有在运行的时候,才能确定真实的类型
2.静态语言:指针指向本类以及本类的子类对象 动态语言:指针可以指向非本类对象
3.指针就是存地址的,所以一个指针变量占据8个字节,可以存任意的地址
#pragma mark - Day06_08_编译检查 1.编译检查:编译的时候,编译器会检查代码是否符合语法规范. 2.根据这个特性,可以通过强制类型转换,欺骗编译器
#pragma mark - Day06_09_运行检查 1.运行检查:运行的时候,会真正的去检查对象中是否存在这个方法
NSString *str = [HMPerson new]; [(HMStudent *)str study];
// 编译的时候,只是去检查这个指针类型中是否存在方法的声明,如果没有说则明无法调用,这是一个语法问题 // 运行的时候,实际上是通过指针中存储的地址访问堆区空间的对象,如果发现该地址对应的对象,没有实现该方法,程序会崩溃 崩溃时会报一个非常经典的错误 unrecognized selector sent to instance 0x100306b30
#pragma mark - Day06_10_NSObject万能指针 NSString *str = [HMPerson new]; [str sayHi]
1.NSObject是OC中所有类的基类 == OC中所有的类都是从NSObject派生出来的 2.根据LSP,NSObject类型的指针,可以指向所有的子类对象(可以指向任意类型的对象) 但是默认情况下,只能调用NSObject类中的方法 NSObject *obj = [HMPerson new];
#pragma mark - Day06_11_id指针 1.id和NSObject类型指针的区别 1.使用NSObject类型的指针,会进行编译检查 2.使用id类型的指针,不会进行编译检查
2.id的局限性 1.id类型的指针不能使用点语法,只能使用[]的形式调用方法 2.id类型的指针不需要进行编译检查,但是需要进行运行检查
#pragma mark - Day06_12_id指针总结 id的本质 通过id可以指向任意的对象 void * 可以理解为OC中的id相当于C语言中的void *
id person = [NSString string]; [person length]; [person count];
#pragma mark - Day06_13_instancetype 1.为了在父类中定义类方法,返回当前类的对象. + (instancetype *)person { return [self new]; }
2.instancetype是什么 是一个类型
3.instancetype的作用 代表方法返回值的类型,这个方法通过哪个类调用,就代表返回的是哪个类的对象
4.instancetype怎么用 只能作为方法的返回值
5.注意点: instancetype和id的区别 instancetype只能作为方法的返回值,不能用在其它场合,代表返回值的类型是当前类的对象 id是一个可以指向任意类型的指针,id是一个无类型的指针,可以使用id声明一个指针变量
#pragma mark - Day06_14_在对象方法中使用self创建当前类的对象 1.在对象方法中,self指向当前对象 2.可以使用self调用class方法,获得当前对象的类 3.使用当前对象的类,创建一个对象 - (instancetype)test { return [self.class new]; }
#pragma mark - Day06_15_动态类型检测 1.动态:程序运行的时候(代码执行的时候)
2.在NSObject类中,有以下四个常用方法 // 判断当前对象是否 "拥有" 或者 "实现" 了指定的方法 // 只要有方法的实现,就没有任何的问题,返回值是YES // 此方法必须要掌握,后面会频繁使用 - (BOOL)respondsToSelector:(SEL)aSelector;
// 以下三个方法了解即可 // 判断当前对象是否是指定类及其子类的类型 - (BOOL)isKindOfClass:(Class)aClass; // 判断当前对象是否是指定类型(不包括其子类) - (BOOL)isMemberOfClass:(Class)aClass; // 判断当前类是否是指定类的子类 + (BOOL)isSubclassOfClass:(Class)aClass;
#pragma mark - Day06_16_构造方法简介 1.new方法的本质 new方法中其实调用了两个两个方法:alloc和init 2.alloc的作用: 在堆区开辟一个合适的区域,创建对象
3.init的作用 1.初始化对象,给对象的成员变量赋默认值: OC指针:nil C指针:NULL 基本数据类型:0 2.非常重要的,必不可少的,但是我们未知的事情
#pragma mark - Day06_17_重写init方法 1.为什么要重写init方法 1.如果想让对象创建出来之后,其中的成员变量不是默认值,而是自己制定的值 2.如果想让对象创建出来的时候,做一些事情 2.怎么重写 目的:在父类的init方法的基础上扩展一些内容:(1.给成员变量赋指定的值;2.在初始的时候做一些事情) 1.先调用父类的init方法 2.父类的init方法,返回值是instancetype,也就是调用方法的对象对应类型的指针 3.判断父类的init方法是否执行成功,如果执行成功,就进行扩展,否则什么也不做 4.返回当前对象 3.规范
- (instancetype)init { self = [super init ]; if (self) { // 给当前对象的成员变量赋指定的值 self.age = 1; self.name = xiaoming } return self; }
1. [HMPerson alloc] init] 2. #pragma mark - Day06_18_自定义构造方法 1.格式规范 - (instancetype)initWithName:(NSString *)name andAge:(int)age { // 对象中的成员变量 self = [super init]; if (self) { // 给当前对象的成员变量赋指定的值 self.age = age; self.name = name; } return self; }
HMPerson *p = [HMPerson alloc ] init]; nil sayHi] 2.注意 1.init方法也叫构造方法 2.在OC里面,只有以init或者initWith开头的方法,编译器才认为是构造方法,才能在其中给self赋值
HMPerson + (instancetype)personWithName:(NSString *)name andAge:(int)age { // HMPerson *person = [self new]; // person.name = name; // person.age = age; return [[self alloc] initWithName:name andAge:age]; }
|