Objective-C核心语法总结
1.点语法
点语法是为了方便其它程序员转入oc
Person *p = [Person new];
p.age = 10; // 其实是[p setAge:10];
int a = p.age; // 其实是 [p age];
p.name = @"Jack";
NSString *s = p.name;
NSLog(@"%@", s);
心得体会:
点语法本质上还是方法的调用,并不是访问对象的成员变量
2.成员变量的作用域
(1)@public : 在任何地方都能直接访问对象的成员变量
(2)@private : 只能在当前类的对象方法中直接访问(@implementation中默认是@private)
(3)@protected : 可以在当前类及其子类的对象方法中直接访问 (@interface中默认就是@protected)
(4)@package : 只要处在同一个框架中,就能直接访问对象的成员变量
int _no; // 默认为protected
@public // 在任何地方都能直接访问对象的成员变量
int _age;
@private // 只能在当前类的对象方法中直接访问
int _height;
@protected // 能在当前类和子类的对象方法中直接访问
int _weight;
int _money;
心得体会:
(1)成员变量不仅可以在累的定义中声明,也可以在类的实现中声明。
(2) @interface和@implementation中不能声明同名的成员变量。
3.property和synthesize的用法
(1)@property:可以自动生成某个成员变量的setter和getter声明
(2)@synthesize自动生成age的setter和getter实现,并且会访问_age这个成员变量
property和synthesize的几种形式,见如下代码
@property int age;
// 上面一行代码等同于
- (void)setAge:(int)age;
- (int)age;
@synthesize age = _age;
// 上面一行代码等同于
(void)setAge(int age)
{
_age = age;
}
(int)age
{
return _age;
}
// 可以写在在一行
@property int speed, wheels;
@synthesize speed = _speed, wheels = _wheels;
// 会访问_speed这个成员变量,如果不存在,就会自动生成@private类型的_speed变量
@synthesize speed = _speed;
@property int speed; // ios4.2之后,@property还包含了@synthesize的功能
心得体会:
(1)@synthesize会访问对象的成员变量,如果不存在,就会自动生成@private类型的变量。
(2)如果类没有声明和实现getter或者setter,其中的一个,则@property会生成另一个,并且生成对应的变量
(3)如果类既声明和实现了gertter和setter,那么就不会自动生成对应的@private类型变量
(4)还有另外一种特殊的形式:@synthesize age;默认会访问age这个成员变量,如果没有age,就会自动生成@private类型的age变量
4.id
id是万能指针类型,能指向或者操作其它任何oc对象
id d = [Person new];
[d setAge:10];
5.构造方法
用来初始化对象的方法,是个对象方法,-开头
// 1.调用+alloc分配存储空间
// Person *p1 = [Person alloc];
// 2.调用-init进行初始化
// Person *p2 = [p1 init];
// 等同于
Person *p4 = [[Person alloc] init];
对象初始化的两种写法(重写init方法)
- (id)init
{
// 1.一定要调用回super的init方法:初始化父类中声明的一些成员变量和其他属性
self = [super init]; // 当前对象 self
// 2.如果对象初始化成功,才有必要进行接下来的初始化
if (self != nil)
{ // 初始化成功
_age = 10;
}
// 3.返回一个已经初始化完毕的对象
return self;
}
- (id)init
{
if ( self = [super init] )
{ // 初始化成功
_age = 10;
}
// 3.返回一个已经初始化完毕的对象
return self;
}
心得体会:
(1)完整地创建一个对象有两步,第一,分配存储空间(+alloc);第二,初始化(init)
(2)一定要调用回super的init方法:初始化父类中声明的一些成员变量和其他属性
自定义构造方法:
// 父类的属性交给父类方法去处理,子类方法处理子类自己的属性
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no
{
// 将name、age传递到父类方法中进行初始化
if ( self = [super initWithName:name andAge:age])
{
_no = no;
}
return self;
}
心得体会
:
(1)自定义构造方法一定是以- 开头,函数名以initWith开头
(2)只是在init方法上加了参数列表,更灵活的初始化对象。
6.分类(category)
在不改变类的模型上,给类扩充一些方法,有利于团队合作
格式:
分类的声明
@interface 类名 (分类名称)
// 方法声明
@end
分类的实现
@implementation 类名 (分类名称)
// 方法实现
@end
#import "Person+MJ.h"
#import "Person.h"
@interface Person (MJ)
- (void)study;
@end
@implementation Person (MJ)
- (void)study
{
NSLog(@"学习-----%d", _age);
}
心得体会:
(1)Category可以访问原始类的实例变量,但不能添加变量,只能添加方法。如果想添加变量,可以考虑通过继承创建子类
(2)Category可以实现原始类的方法,但不推荐这么做,因为它是直接替换掉原来的方法,这么做的后果是再也不能访问原来的方法
(3)多个Category中如果实现了相同的方法,只有最后一个参与编译的才会有效
7.类的本质
其实类也是一个对象,是Class类型的对象,简称“类对象”
+load和+initilize
+load
(1) 在程序启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法
(2)先加载父类,再加载子类;也就是先调用父类的+load,再调用子类的+load
(3)先加载元原始类,再加载分类
(4)不管程序运行过程有没有用到这个类,都会调用+load加载
+initialize
(1)在第一次使用某个类时(比如创建对象等),就会调用一次+initialize方法
(2)一个类只会调用一次+initialize方法,先调用父类的,再调用子类的
获取类对象的方式:
Class c = [Person class]; // 类方法
Class c2 = [p class]; // 对象方法
心得体会:
(1)类名就代表着类对象,每个类只有一个类对象。
(2)先通过Class创建类对象,再通过类对象创建类型对象。
8.description方法
-description方法:使用NSLog和%@输出某个对象时,会调用对象的-description方法,并拿到返回值进行输出+description方法:使用NSLog和%@输出某个类对象时,会调用类对象+description方法,并拿到返回值进行输出
心得体会:
(1)通过重写-description和+description方法,来修改NSLog的输出。
(2)如果在-description方法中使用NSLog打印self会造成死循环。
10. SEL
SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址。找到方法地址就可以调用方法
// SEL对象的创建
SEL s = @selector(test);
SEL s2 = NSSelectorFromString(@"test");
// SEL对象的其他用法
// 将SEL对象转为NSString对象
NSString *str = NSStringFromSelector(@selector(test));
Person *p = [Person new];
// 调用对象p的test方法
[p performSelector:@selector(test)];
// 下面的代码会引发死循环
- (void)test {
[self performSelector:_cmd]; // _cmd :代表着当前方法的SEL
}
心得体会:
(1)其实给对象发送消息,这个消息就是SEL,把方法封装成SEL数据,然后去找对应的方法低值,最后调用方法。
(2)每个方法都有一个与之对应的SEL类型的对象