您的位置:首页 > 移动开发 > IOS开发

IOS学习---OC基础学习4

2014-10-23 22:46 253 查看
点语法:

Person类中有_age一个成员变量;

设置成员变量_age的值:

Person *p = [Person new]

p.age = 10;[p setAge:10];

获取成员变量的值:

int a = p.age;[p age];

根据有无赋值判断是get方法还是set方法

点语法的本质还是方法调用(可通过在set和get方法中设置验证语句验证)

单步调试在Xcode中底面输出栏上面类似下载的按钮

成员变量作用域:

当类在声明成员变量时加入@public,那么在任何地方都可以直接访问对象的成员变量

当类在声明成员变量时加入@private,那么不允许直接访问类的成员变量只能使用set和get方法(只能在当前类的方法对象方法中直接访问)

当类在声明成员变量时加入@protected,那么只能在当前类和子类的对象方法中直接访问(默认为protected)

类的成员变量 既可以在.h(声明文件)文件中声明 也可以在.m(实现文件)文件中声明。但是在.h文件中声明默认是protected而在.m文件中声明默认是privated类型(也可以通过setter和getter方法访问)(注意:成员变量名不能与声明文件中的成员变量名相同)(原因:其他文件无法import.m文件因此其他文件无法使用该成员变量)

@property int age;相当于生成age的set和get方法;

@synthesize age(方法声明名) = _age(成员变量名):

自动生成@property声明 age的setter和getter方法,并且会访问—_age这个成员变量

也可以同时实现几个方法

@synthesize age=_age,name=_name;

@synthesize age=_age,name=_name;

执行此句时会访问_speed这个成员变量,如果不存在,就会自动生成@private类型的_speed变量

缺点:自动生成的类型为private类型

注意:如果写为:

1、@synthesize age;则会自动生成名字为age(不是_age)的成员变量的set和get方法

2、如果@implementation中已经有了set和get方法 在使用@synthesize时不会自动生成以_下划线开头的成员变量

id类型:

万能指针,能指向\操纵任何OC对象

id d = [Person new];//注意id后面没有*号

相当于

NSObjct *o = [Person new]; // 多态 id = NSObject*

id 相当于可以指向任何一个NSObjct的子类,形成类似多态的形式

构造方法:

Person *p = [Person new];

完整的 创建一个可用对象

1.分配存储空间 +allo

2.初始化 -init

1、调用+alloc分配存储空间

Person *p = [Person alloc];

2、调用-init进行初始化

Person *p2 = [p1 init];

1+2 = Person *p = [Person new];

也可以写为:Person *p3 = [[Person alloc] init];

以后创建新的对象不要在用new了 改为两步走

构造方法:用来初始化的方法,是一个构造方法(-开头)

重写构造方法:

例子:重写init方法

- (id)init

{

//1、一定要调用回super(父类)的init方法:初始化父类//中声明的一些成员变量和其他属性

self = [super init];//当前对象self

if(self !=nil); // nil==0

{

//2初始化成功 才有必要进行接下来的初始化

_age = 10;//初始化

}

//3、返回一个已经初始化完毕的对象

return self;

}

可以简写为

- (id)init

{

//super调用的是直接父类

if(self = [super init]); // nil==0

{

_age = 10;

}

return self;

}

总结:

重写构造方法的目的:

为了让对象创建出来,成员变量就会有一些固定的值

重写构造方法的注意点:

1、先调用父类的构造方法(self = [super init])

2、在进行子类内部成员变量的初始化

自定义构造方法:

1、一定是对象方法,一定以-开头

2、返回值一般为id类型

3、方法名一般以init开头

例子:

- (id)initWithName:(NSString*)name;

- (id)initWithName:(NSString*)name

{

if(self = [super init])

{

_name = name;

//如果遇到某些父类的变量为私有变量

[self setName:name];

[super setName:name];

sefl.name=name;

}

return self;

}

调用:Person *p = [[Person alloc] initWithName:@"rose"];

写程序时:能调用原来的程序就不要重复写原来的代码!

谁声明的变量由谁来进行赋值

父类的属性(成员变量)交给父类来处理,子类方法处理子类自己的属性(成员变量)

分类(Category )(类别、类目):

可以给某个类扩充一些方法(不修改原来的代码)

//声明

@interface 类名[分类名称]

@end

//实现

@implementation 类名[分类名称]

@end;

作用:在不改变原来类内容的基础上 可以为类增加一些方法

使用注意:

1、不能扩充成员变量,只能添加方法

2、新增的分类中可以访问成员变量

3、可以直接使用对象调用分类中的方法 分类-原来的类-父类

4、分类的优先级最高,对象调用方法时优先在分类中查找,因此如果分类中重写类中的某个方法,会覆盖掉原来类中的方法,从而导致原来的方法失效

5、方法调用优先级:分类(最后参与编译的分类优先)->原来类->父类

类的本质”

类也是一个对象 是一个class类型的对象 简称类对象

class 类型的定义

typedef struct objc class *class

class 创建 Person类对象

利用Person类对象 创建Person类型的对象

Person *p1 = [[Person alloc] init];

Person *p2 = [[Person alloc] init];

//获取内存中的类对象

class c = [p class];

class c2 = [p2 class];

c 与 c2是相同的

因为p1,p2都是Person类的对象所以内存中的对象类相同

(类对象是否相同可根据对象中的isa的指向进行判断)

另一种获取内存中类对象的方法

class c3 = [Person class];

最终搞得输出结果 c =c2 = c3;

一个类在内存中只有一个存储空间 我们称其为类对象

类的加载顺序:先加载父类 在加载子类

load方法:在类被加载的时候调用 只会被加载一次

initialize方法:当程序启动的时候,会加载一次项目中所有的类,类加载完毕后就会调用load方法

(面试内容)

load方法:程序一启动,加载类的时候被调用,每个类调用一次

initialize方法:第一次用到这个类的时候被调用,总是先调用父类

总结:

1、当程序启动时,就会加载项目中所有的类和分类,而且加载后会调用每个类和分类的+load方法,只会调用一次、

2、当第一次使用某一个类时,就会调用当前类的+initialize方法

3、先加载父类,在加载子类(先调用父类的+load方法,在调用子类的+load方法)

先初始化父类,在初始化子类(先调用父类的+initialize方法,在调用子类的+initialize方法)

Description:

-description

默认情况下利用NSLog和@输出对象时,结果是<类名:内存地址>

Person *p = [[Person alloc] init];

NSLog(@"%@",p);

执行上述第二句时:

1、会调用对象P的-description方法

2、拿到-description方法的返回值(NSString*)显示到屏幕上

3、-description方法默认返回值是 “类名+内存地址”

因此,要想通过NSLog(@"%@",p)输出p的相关信息就要重写

-description方法

+description:

Class c = [Person class];

NSLog(@"%@",c);

执行上述第二条语句时

1、会调用类的+description方法

2、拿到+description方法的返回值(NSString*)显示到屏幕上

3、+description方法的默认返回值为“类名”

NSLog的扩展输出:

1、NSLog(@"%d",__LINE__);输出当前的行号

//NSLog输出C语言字符串时 不能有中文

2、NSLog(@"%s",__FILE__);输出文件路径(文件路径中不能有中文)

3、NSLog(@"%d",__LINE__);输出当前函数或者方法名

self基本使用:

多种方法调用类中的方法

Person *p = [[Person alloc] init];

[p test2];

执行步骤:

基础:

先利用对象P中的isa指针 到Person类中去寻找 test2方法

而 在Person类中每一个 方法都对应这一个self类的数据(方法的地址)改地址存放于isa指针当中

具体步骤:

1、把test2包装成SEL类型数据

2、去isa中的SEL地址 到Person类中查找对应的方法

3、根据方法地址调用相应的方法

调用方法的两种方法:

1、直接调用

[p test];

第二种 利用SEL=方法名地址

[p performSelector:@selector(test2)];

第三种

每个方法内部都会隐藏一个_cmd 代表当前方法

总结:

SEL其实是对方法的一种包装,将方法包装秤一个SEL类型的数据,去找到相应的方法地址,找到方法地址就可以调用方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: