核心与法
点语法
>点语法的本质是方法调用
>当使用点语法时,编译器会自动展开成相应的方法
注意:self.age = age;会引发死循环
.h声明文件
#import <Foundation/Foudation.h>
@interface Person : NSObject
{
int age;
}
- (void)setAge:(int)age;
- (void)age;
@end
.m方法实现文件
@implementation Person
- (void)setAge:(int)age
{
_age = age;
NSLog(@"set");
}
- (void)age
{
return _age;
NSLog(@"get");
}
@end
main.m文件
#import <Foundation/Foudation.h>
#import "Person.h"
int main()
{
Person *p = [Person new];
// [p setAge:10];
// int a = [p age];
// 点语法的本质还是方法调用,自动转为[p setAge:10];
p.age = 10;
int a = p.age;
NSLog(@"%d",age);
return 0;
}
成员变量的作用域
概念:局部变量、全局变量都有自己的作用域,成员变量也不例外
类型:
>@private:只能在当前类的实现@implementation中直接访问
>@protected:可以在当前类以及子类的实现@implementation中直接访问
>@public:任何地方都可以直接访问
>@package:同一个体系内(框架)访问,介于@private和@public之间
继承补充
>父类(超类)super
>子类subclass\subclasses
>单继承
implementation补充
没有@interface,只有@implementation,也可以开发一个类
关键字@property和@synthesize
@property:可以自动生成某个成员变量的setter和getter的声明
@synthesize:自动生成成员变量的setter和getter实现方法,并且会访问这个成员变量
.h文件
#import <Foundation/Foudation.h>
@interface Person:NSObject
{
int _age;
int _height;
}
// 自动生成setter和getter方法的声明
@property int age;
/*相当于
- (void)setAge:(int)age;
- (int)age;
*/
@property int height;
@end
.m文件
#import "Person.h"
@implementation Person
// @synthesize age = _age;自动生成age的setter和getter实现方法,并且会访问_age这个成员变量
@synthesize age = _age;
@synthesize height = _height;
@end
main.m文件
#import <Foundation/Foudation.h>
#import "Person.h"
int main()
{
Person *p = [Person new];
p.age = 10;
}
@synthesize细节
@synthesize age = _age;
>setter和getter中会访问成员变量age
>如果_age不存在,就会自动生成一个@private的成员变量_age
@synthesize age;
>setter和getter实现中会访问成员变量age
>如果成员变量age不存在就会自动生成成员变量age
手动实现
若手动实现了setter方法,编译器会自动生成getter方法
若手动实现了getter方法,编译器就会自动生成sette方法
若同时手动实现了setter和getter方法,编译器就不会生成不存在的成员变量
@property新特性
Xcode 4.x之后,@property独揽了@synthesize的功能
默认情况下,setter和getter方法的实现,会去访问下划线_开头的成员变量
id
简介:万能指针,能指向(操纵)任何对象,相当于NOSbject
定义:typedef struct objc_object{
Calss isa;
} *id;
使用:
int main()
{
// 等价的语句
// id d == NSObject *
Person *p = [Person new];
id d = [Person new];
return 0;
}
局限性:调用一个不存在的方法,编译器会马上报错
构造方法
简介:用来初始化对象的方法,是一个对象方法,-开头
重写构造方法的目的:为了让对象创建出来,成员变量就会有一些固定的值
重写构造方法的注意点
》先调用父类的构造方法(self = [super init])
》再进行子类内部成员变量的初始化if(self !=0){}
int main()
{
Person *p = [Person new];
/*
完整地创建以一个可用的对象
》分配存储空间 +alloc
》初始化 -init
*/
// 1.调用+alloc分配存储空间
Person *p1 = [Person alloc];
// 2.调用-init进行初始化
Person *p2 = [p1 init];
// 1.和2.整合为一句,比较好的写法
Person *p3 = [[Person alloc] init];
// 每个Person对象创建之后,他的_age都是一个定值,比如10,重写.m里面的-init方法
Student *stu = [[Person alloc] init];
return 0;
}
@implementation Person
// 重写- init方法,使_age初始化为10
- (id)init
{
// 1.一定要调用super的init方法:初始化父类声明的一些成员变量和其他属性
self = [super init]; // 当前对象self
// 2.如果对象初始化成功,才有必要进行接下来的初始化
if(self != nil)
// 1.和2.可以合并为if(self = [super init])
{
// 初始化成功
_age = 10;
}
// 3.返回一个已经初始化完毕的对象
return self;
}
@end
#import "Person.h"
// 重写学生对象,初始化使学生的年龄是10,学号是1
@implementation Person
- (id)init
{
if(self = [super init])
{
_no = 1;
}
}
@end
自定义构造方法
/* 自定义构造方法的规范
》一定是对象方法,以-开头
》返回值一般是id类型
》方法名以init开头
*/
Person.h
@interface Person:NSObjcet
@property NSString *name;
// 固定书写格式
- (id)initWithName:(NSString *)name;
- (id)initWithAge:(int)age;
- (id)initWithName:(NSString *)name andAge:(int)age;
@end
Person.m
#import "Person.h"
@impelmentation Person
- (id)init
{
if(self = [super init])
{
_name = "jack";
}
return self;
}
- (id)initWithName:(NSString *)name
{
if(self = [super init])
{
_name = name;
}
return self;
}
- (id)initWithAge:(int)age
{
if(self = [super init])
{
_age = age;
}
return self;
}
- (id)initWithName:(NSString *)name andAge:(int)age
{
if(self = [super init])
{
_name = name;
_age = age;
}
return self;
}
@end
main.m
#import <Foundation/Foudation.h>
#import "Person.h"
int main()
{
Person *p = [[Person alloc] init];
NSLog(@"12345");
Person *p2 = [[Person alloc] initWithName:@"rose"];
Person *p3 = [[Person alloc] initWithAge:20];
Person *p4 = [[Person allco] initWithName:@"jim" andAge:30];
return 0;
}
子类Student继承上面的父类
原则:父类的属性由父类方法去处理,子类方法处理子类自己的属性
修改模板路径
xcode -> content ->developer ->library ->xcode ->templates ->project templates ->mac ->application ->command line ->templateinfo.plist ->descrip/->definitions
分类(category)
可以给某一个类扩充一些方法(不改变原来类的代码)
作用:在不改变原来类内容的基础上,可以为类增加一些方法
格式
》声明
@interface 类名(分类名称)
@end
》实现
@implementation 类名(分类名称)
@end
使用场景
》
使用注意
》分类只能增加方法,不能增加成员变量
》分类方法实现中可以访问原来类中声明的成员变量
》分类可以重新实现原来类中的方法,但会覆盖掉原来的方法,会导致原来的方法没法再使用
》方法调用的优先级:分类(最后参与编译) -》原来类 -》父类
分类给NSString增加方法
给NSString增加一个类方法,计算某个字符串中阿拉伯数字的个数
给NSString增加一个对象方法,计算当前字符串中阿拉伯数字的个数
类库:很多类的集合
类的本质:类本身也是个对象,是个class类型的对象,简称类对象
获取类对象的方式
1》Class c = [Person class];
2》Person *p = [Person new];
类对象调用类方法
Class c = [Person class];
Person *p2 = [c new];
类的加载和初始化:
》当程序启动时,就会加载项目中所有的类和分类,而且加载后会调用每个类和分类的+load方法,指挥调用一次
》当第一次使用某个类时,就会调用当前类的+initialize方法
》先加载父类,再加载子类(先调用父类的+load方法,再调用子类的+load方法),先初始化父类,再初始化子类(先调用父类的+initialize方法,再调用子类的initialize方法)
+load
》程序在启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法
》先加载父类,再加载子类:也就是先调用父类的+load,再调用子类的+load
》先加载元原始类,再加载分类
》不管程序运行过程有没有用到这个类,都会调用+load加载
+initialize
》在第一次使用某个类时(比如创建对象),就会调用一次+initialize方法
》一个类只会调用一次+initialize方法,先调用父类的,再调用子类的
description方法
-description:使用NSLog和%@输出某个对象时,会调用对象的-description方法,并拿到返回值进行输出
+description:使用NSLog和%@输出某个类对象时,会调用类对象的+description方法,并拿到返回值进行输出
SEL方法
》每个类的方法列表都存储在类对象中
》每个方法都有一个与之对应的SEL类型对象
》根据SEL对象就可以找到方法的地址,进而进行调用
》SEL类型的定义
typedef struct objc_selector *SEL;
SEL对象的创建
SEL s = @selector(test);
SEL s2 = NSSelectorFromString(@"test");
Person.h
|
|