OC---知识点

来源:互联网 发布:淘宝买steam游戏步骤 编辑:程序博客网 时间:2024/05/16 12:29


命名规则:

1、get、set方法:

set:以set开头,成员变量大写

get:与成员变量同名

注:并不是所有的成员变量都需要get、set方法,对应那些只读、只写的变量,不一定要提供

2、成员变量

以_开头

3、类方法、对象方法

类方法  +  开头,以类调用

对象方法 -开头,以对象调用

注:

  • 不能用对象调用类方法,如果是对象调用的方法,它会到对象里寻找以- 开头的方法、

会报 [person test] unrecognized  selector send to instance OX ...

  • 允许类、对象方法同名,但不允许同名的对象方法

语法规则:


1、类也会有存储空间,里面放方法列表,每个对象都有isa指针,指向对象所对应的类(跟随);每个类里有关supperclass指针,指向父类。

当遇到一个方法时,根据isa指针,找到该类,如果没有找到这个方法,在根据类里的supperclass指针,在父类里寻找,直到找到该方法为止。


2、类对象 ==

  • 类 是class类型的对象,一个类只有一个类对象
  • 类加载的时候先利用class创建person类对象,之后再利用person类对象创建person类的实例对象
  • 获取类对象(C是指针,不用加*了)
Class c=[p class];Class c=[Person class];Person *p=[];//打印地址NSLog(“c=%p”,p);
  1. 当程序一启动,就会把所有类、分类加载进来(类加载完毕后调用+voidload方法):先加载父类,然后是子类,先加载原始类,在加载分类。
  2. 当第一次使用这个类的时候,会调用initialize方法,会优先调用分类的方法,先调用父类,然后是子类([[Student alloc]init])。
  3. 所有类的load方法总是都会被调用;但initialize方法只在第一次使用的时候才会被调用,并且优先加载分类的(就不会加载原来类的initialize了)

监听:如果想在类第一次被使用的时候,进行一些操作,可以重写initialize。


3、继承

1、父类的  声明    要放前面

2、不允许子类和父类拥有相同的成员变量,

3、方法实现可以相同(重写);父类、子类方法相同,优先调用子类的

单继承

缺点:代码耦合性太强,类之间的关系太强了


4、成员变量的作用域

作用域的意思是变量能不能直接访问

@public任何地方

@private  只能在当前类的对象方法中直接访问(->

@protected只能在当前类和其子类的对象方法中直接访问(->

@package在同一个框架中,就能访问

注:

1、虽然子类中不能访问私有的成员变量,但子类是拥有这些成员变量的,可以通过setget方法访问。

2、声明中默认是@protected;实现中的成员变量默认是私有的;

   实现中如果写成员变量,名字不能和声明中的一样,冲突-不常用(即便写成public也没用,对于其他的类是不可见的,因为其他的类包含的是头文件,没有包含它)

5、构造方法

1New   +  返回值为id

分配存储空间 +alloc

初始化 -init(构造方法)

2、重写init  步奏

1、调用[super init],初始化父类成员变量,self=[super init]

2、父类初始化成功,初始化当前对象:self=nil_size=10

3、Return self

-(id)init{   If(self=[super init]){      _size=10;   }Return self;}

3、自定义构造器

规范:

1、是对象方法

2、返回值id

3、方法名init开头,如,initWithName:(NSString *name;     :以name初始化构造器,初始化时调用这个方法

- (id) initWithName:(NSString *)name age:(int)age score:(int)score{if(self=[super init]){_name=name;_age=age;_score=score;}return self;}


注:

如果想要初始化的变量是父类的私有变量,怎么初始化呢?Super.age=age

但是,父类的变量,要放在父类初始化:子类不要多管闲事


6、很多时候系统自带的类并不能满足我们的需求,我们可以给其扩充方法:如下,为NSString扩充方法。

实现:

- (int)numberCount{   Int count=0;   For(int i=0;i<selflenth;i++){      Unichar c=[self characterAtIndex:i];      If(c>’0’ && c<=’9’){         Count++;      }   }   Return count;}

调用:

Int count =[@”fdscdgbhgfdcf”  numberCount];


7、@property、@synthesize关键字

作用:自动生成set、get方法

声明: @property (nonatomic,assign) int size(size 是去掉成员变量的_);自动生成 成员变量size 的get、set方法,

- (void)setSize:(int)size;- (int)size;
@property (nonatomic,retain) Car *car

实现:在.m文件中加上

@synthesize size=_size;

  • 自动生成property为size的实现(get、set),并且会访问成员变量_size,如果不存在会自动在.m文件中生成私有的_size(成员变量不用写啦!)。
  • @synthesize size;默认会访问成员变量size,如果没有成员变量size,Xcode会自动生成私有的成员变量size
  •  实际是@synthesize size=_size 也不用写啦,@property 会把@synthesize size=_size也做啦,它会默认访问以_开头的成员变量(如果没有,创建)!(Xcode4.4后)。

作用相当于:

- (void)setSize:(int)size{    _size=size;}- (int)size{    Return _size;}

在@property后面的括号中可以出现四种类型的参数:

  • set方法内存管理相关参数

    • retain:release旧值,retain新值(适用于OC对象)。
    • assign:(默认)直接赋值(非OC对象)。
    • copy:release旧值,retain新值(适用于OC对象)。
  • 是否生成set方法

    • readwrite:(默认)同时生成get、set的声明、实现。
    • readonly:只有get。
  • 多线程管理

    • nonatomic:性能高(一般用这个)
    • atomic:(默认)
  • set、get方法名称(一般用于bool类型)

@property (setter=setRich:,getter=isRish) Bool rich;

关于BOOL

本质:

typedef signed char BOOL;
两种取值:YES/NO

#define YES (BOOL)1#define NO  (BOOL)0
输出:
NSLog(@"%d %d", YES, NO);

注:

  1. 如果get、set方法自己有,会访问自己的;如果全有,不会帮你生成_size了。
  2. 基本数据类型是不可以加retain的:@property (retain) int*age;int怎么可以调用retainrelease

  3. 对应括号中的参数:同种类型的方法,不能同时出现;不同类型的方法,可以。

  4. nonatomic,retain比较常用。


8、self关键字

作用:是指向当前对象的指针,代表方法调用者:调用者是类时,代表类;调用者是对象时,代表对象;调用者是父类时,代表父类,调用者是子类时,代表子类。

使用情况:

  1. 局部变量名称和成员变量名称一样,使用成员变量,self->_age,
  2. 调用当前对象(父/子)的方法,[self bark];
  3. self出现在对象方法中,调用对象方法;self出现在类方法中,调用类方法

9、super关键字

作用:[super bark] :调用父类的bark方法

super出现在对象方法中,调用父类的对象方法;出现在类方法中,调用父类方法


10、点语法 

作用:Oc的点语法,与java不同,不是成员变量的赋值,本质是方法调用;

编译器看到是点语法,先自动转换为[  ],如果有赋值:Stu.age=10;,自动转成 [Stu setAge:10];如果没有赋值:int a=Stu.age,自动转成 int a=[Stu setAge]

注:

使用点语法需要有setget方法。

Oc中访问成员变量只有一种方法->


11、id关键字

Id是万能指针,可以操作任何oc对象:id d=[Person new];

Id 相当于NSObject *


12、category分类 

作用:是在不改变某个类的情况下,给某个类扩充方法,分类更有利于团队的开发,只要包含分类的头文件就行。

1、分类名称以模块命名,对于 Person 的 分类MJ  ,分类文件的名称是:Person+MJ.h

2、可以这样声明或实现:

@interface 类名(分类名)- (void) study;@end

3、这样调用:

[p study]

注意:

· 分类不可以扩充成员变量

· 分类可以访问原来类(person类) 的成员变量

· 分类的优先级最高。调用一个方法,先在分类里找,其次是原来的类,然后是父类,所以如果分类重写了原来类的方法,会导致原来的方法会被覆盖,不建议

 

13、description方法--(跟toString似得)

作用:重写description,打印对象:NSLog(@“%@”,p);,打印对象的时候自动调用description方法。

打印实例对象

重写时,description是对象方法,返回值是OC字符串

例如:

- (NSString *)description{   //NSString的字符串拼接用的是stringWithFormat   Return [NSString stringWithFormat:@”name is%@”,_name];}

+打印类对象

类方法:打印类对象

Class  c=[Person class];NSLog(@“%@”,c);


14、NSLog打印

NSLog输出C语言字符串%s,不允许有中文

NSLog(@“%s”,_FILE_):输出文件路径

可以用printf(“%s”,_FILE;

NSLog(@“%s”,_func_):输出函数名

%p  地址

%d

%@


15、SEL数据

在类进行加载的时候,把每一个方法的地址(如,test()方法)赋值给了一个SEL数据如t在去调用test()方法的时候,[p test],编译器把test方法包装成一个SEL数据, 根据这个SEL数据,在内存中找到方法的地址,但是,问题是:

[p test]包装成的SEL数据,和  在类对象中的SEL数据(test对应的SEL),怎么保持一致?

每个方法内部都包含一个SEL类型的数据:_cmd,代表当前方法(test),可以通过将SEL数据转换成字符串打印出来

NSString *s=NSStringFromSelector(@selector(test));

 

创建SEL数据

根据方法名创建SEL类型数据

SEL s=@selector(test);

根据方法名字的字符串创建SEL数据

SEL s=NSSelectorFromString(@”test”);

调用

[p perFormSelector:@selector(test:) withObject:@”sdad”];  带参数的[p perFormSelector:s];

 16、@class关键字

作用:@class Person;,仅仅告诉编译器Person是个类 ,

使用:在.h中声明类,在.m文件中使用import引入类

使用场景:循环引用

优点:

1、解决了循环引用
2、提高编译效率。在A类的头文件中,如果以import的方式引入B类,当B类发生改变的时候,A类还要重新编译一下,如果B类被很多地方引入了,效率可想而知!使用@class Person只是声明一个类,仅仅告诉编译器Person 是个类,但并没有把类的所有细节引入进来。只是在具体使用的时候才,import这个类。

 

和#import的区别#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在A.h文件中 B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息如果有上百个头文件都#import了同一个文件,或者这些文件依次被#improt,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的,而相对来 讲,使用@class方式就不会出现这种问题了在.m实现文件中,如果需要引用到被引用类的实体变量或者方法时,还需要使用#import方式引入被引用类

17、block

block也是数据类型

苹果官方建议尽量多用block。在多线程、异步任务、集合遍历、集合排序、动画转场用的很多

block可以这么使用:

int (^myBlock)(int,int)= ^(int a,int b){return a+b;};NSLog(@"%d",myBlock(1,2));

如果没有参数,可以:

void (^myBlock)()= ^(){};
也可以使用typedef定义类型,以后就可以利用MyBlock这种类型来定义block变量,在使用

typedef int (^SuanshuBlock)(int,int);...SuanshuBlock sum=^(int a,int b){return a+b;};SuanshuBlock sub=^(int a,int b){return a-b;};
注意:

block内部可以访问外面的变量
 默认情况下,block内部不能修改外面的局部变量
 给局部变量加上__block关键字,这个局部变量就可以在block内部修改

    int a = 10;    __block int b = 20;    void (^block)();    block = ^{        // block内部可以访问外面的变量        //NSLog(@"a = %d", a);        // 默认情况下,block内部不能修改外面的局部变量        // a = 20;        // 给局部变量加上__block关键字,这个局部变量就可以在block内部修改        b = 25;    };    block();

但是,block,究竟是干什么的呢?以后,用到的时候,在说吧。。。


18、protocol协议

作用:声明方法(没有成员变量),可以在任何类去实现;只要一个类遵守一个协议,就拥有了该协议的所有方法声明。

使用协议:

#import <Foundation/Foundation.h>@protocol myProtocol//必须实现,不实现会有警告,不会报错,用于程序员之间交流,别人一看,就知道,这些方法必须实现。@required- (void)test;//可以不实现@optional- (void)test1;@end

#import <Foundation/Foundation.h>//#import "myprotocol.h"@protocol myprotocol; //原则:真正用到的时候,在import,不管是协议还是类。@class@interface Person : NSObject <myprotocol>@property (nonautomatic,strong) id<myprotocol>;@end
#import "Person.h"#import "myprotocol.h"@implementation Person - (void)test{}@end
 // 要求obj3保存的对象必须是遵守是MyProtocol这个协议        //NSObject<MyProtocol> *obj3 = [[NSObject alloc] init];    id<MyProtocol> obj4 = [[Person alloc] init];    // 要求obj5,保存的对象必须遵守MyProtocol3、并且继承了Person    Person<MyProtocol3> *obj5 = [[Person alloc] init];    

 1.协议的定义

 @protocol 协议名称 <NSObject>
  // 方法声明列表....
 @end


@protocol TicketDelegate <NSObject> 

 
 2.如何遵守协议
 1> 类遵守协议

 @interface 类名 : 父类名 <协议名称1, 协议名称2>
 
 @end

@protocol myprotocol;@interface Person : NSObject <myprotocol>//<span style="font-size:14px;">拥有一个代理属性</span>@property (nonautomatic,strong) id<myprotocol>;@end

 
 2> 协议遵守协议

 @protocol 协议名称 <其他协议名称1, 其他协议名称2>
 
 @end

 
 3.协议中方法声明的关键字

 1> @required (默认)  要求实现,如果没有实现,会发出警告
 
 2> @optional  不要求实现,怎样不会有警告

 
 4.定义一个变量的时候,限制这个变量保存的对象遵守某个协议

 类名<协议名称> *变量名;
 id<协议名称> 变量名;
 NSObject<MyProtocol> *obj;
 id<MyProtocol> obj2;
 
 如果没有遵守对应的协议,编译器会警告

 
 5.@property中声明的属性也可用做一个遵守协议的限制

 @property (nonatomic, strong) 类名<协议名称> *属性名;
 @property (nonatomic, strong) id<协议名称> 属性名;

@property (nonatomic, strong) Dog<MyProtocol> *dog;@property (nonatomic, strong) id<MyProtocol> dog2;


 
 6.协议可用定义在单独.h文件中,也可用定义在某个类中

 1> 如果这个协议只用在某个类中,应该把协议定义在该类中
 
 2> 如果这个协议用在很多类中,就应该定义在单独文件中

 
 7.分类可用定义在单独.h和.m文件中,也可用定义在原来类中

 1> 一般情况下,都是定义在单独文件
 2> 定义在原来类中的分类,只要求能看懂语法

注意:

  • 子类遵守父类的协议
  • 单继承,实现多个协议
  • 定义协议的时候都要遵守基协议:NSObject
  • @protocol myprotocol; 跟@class类似  ,原则:真正用到的时候,在import,不管是协议还是类。


协议的使用见:

http://blog.csdn.net/le_shuo/article/details/41213773


字符串NSString *name=@”sfder”;Int a=[name length]; 是字数,强制转换为int



编译是单文件编译



0 0
原创粉丝点击