#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];
}
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |