object-c(3)

来源:互联网 发布:c语言头文件作用 编辑:程序博客网 时间:2024/05/17 01:10

一些特别的概念

分类

分类(category) 又称类别,  在不修改原有的类的基础上增加新的方法. 有点像c++,继承之后可以添加自己的方法。

#import <Foundation/Foundation.h>@interface Person : NSObject{    NSString *name;    int age;}
@end

如果现在要往类Person中添加一个新的方法 

  -(void) addCate:(NSString*) cate;

新建一个PersonCategory 类,产生.h,.m两个文件。
在PersonCategory.h文件 将PersonCategory改为Person
#import <Foundation/Foundation.h>#import "Person.h"@interface Person(cate)-(void) addCate:(NSString*) cate;@end
PersonCategory.m文件
#import "PersonCategory.h"@implementation Person(cate)-(void) addCate:(NSString *)cate{    NSLog(@"dafdasfdsa=%@",cate);}@end
Person *peron=[[Person alloc] init];
[peron addCate:@"safdasfds"];
当然调用addCate方法需要引入文件PersonCategory.h 文件。
协议
协议(Protocol) ,就是规定一些方法, 让其他的类遵循,遵循的方式就是在类中重写这些方法。而定义协议必须使用protocol关键字。

#import <Foundation/Foundation.h>@protocol ProtocolCom<NSObject> //默认是<NSObject> 可以省略@required//用于表示协议中该方法必须在类中实现,默认[如果不加则默认为@required]-(void) eat;@optional//用于表示协议中该方法在类中可以选择实现-(void) write;@end

#import <Foundation/Foundation.h>
#import "ProtocolCom.h"@protocol MyProtocol <ProtocolCom>  
@required-(void) setname;@optional-(void) setage;
@end

在类中使用协议

#import <Foundation/Foundation.h>#import "MyProtocol.h"@interface Student : NSObject<MyProtocol>@end-------------------------------------------#import "Student.h"@implementation Student-(void) setage{    NSLog(@"Student---setage");}-(void) setname{    NSLog(@"Student----setname");}@end
复制代码
同时遵循多个协议

@interface className:parentName<ProtocolName1,ProtocolName2,...>

conformsToProtocol 方法用于判断某个类是否遵循某个协议,返回值为bool类型

bool flag1=[child conformsToProtocol:@protocol(NewProtocol)];

委托代理delegate

就是不想按照协议的写法来实现函数而已.

如:类A B遵循了协议  C也遵循协议 但不想在类中有实现协议中函数的代码  就可以通过委托 调用 A 或B实现的协议中的函数。

#import <Foundation/Foundation.h>#import "ProtocolName.h"@interface Student : NSObject{    id<ProtocolName> delegate;}@property (retain) id<ProtocolName> delegate;-(void) setMethod;@end---------------------------------------------#import "Student.h"@implementation Student@synthesize delegate;-(void) setMethod{    NSLog(@"Student---setMethod");    [delegate first];    [delegate second];}@end
调用:
Student *stu=[[Student alloc] init];        StudentA *stua=[[StudentA alloc] init];        StudentB *stub=[[StudentB alloc] init];        stu.delegate=stua;        [stu.delegate first];        [stu setMethod];                stu.delegate=stub;        [stu setMethod];



动态判断和选择器

 SEL 类

SEL是选择器(selector)的一个类型。选择器就是指向方法的一个指针。

SEL对象的创建

  1. SEL s1 = @selector(test1); // 将test1方法包装成SEL对象  
  2. SEL s2 = NSSelectorFromString(@"test1"); // 将一个字符串方法转换成为SEL对象 

  • 在内存中每个类的方法都存储在类对象中
  • 每个方法都有一个与之对应的SEL类型的数据
  • 根据一个SEL数据就可以找到对应的方法地址,进而调用方法

下述语句设置了一个button对象上的Action为 “@selector (start:)”,即它调用start方法:

  1. [button setAction:@selector(start:)]; 

如果你的方法上有两个参数,比如:

  1. -(void)setName:(NSString *)name age:(int)age; 

那么,你的选择器应该这样书写:

  1. SEL  sel  = @selector(setName:age:); 

如果方法不存在的话,调用该方法的应用可能会异常中止。所以,需要使用respondsToSelector 方法来判断该对象是否存在对应的方法,使用performSelector:withObject:方法来调用选择器:

  1. SEL  sel  = @selector (start:) ; // 指定action  
  2. if ([obj respondsToSelector:sel]) { //判断该对象是否有相应的方法  
  3. [obj performSelector:sel withObject:self]; //调用选择器方法  

SEL的调用方式:

- (id)performSelector:(SEL)aSelector;- (id)performSelector:(SEL)aSelector withObject:(id)object;- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;- (BOOL)respondsToSelector:(SEL)aSelector;
  1. @interface Person : NSObject 
  2.  
  3. - (void)test1; 
  4.  
  5. - (void)test2:(NSString *)str; 
  6.  
  7. @end 

  1.  Person *person = [[Person alloc] init]; 
  2.      
  3.     // 1.执行这行代码的时候会把test2包装成SEL类型的数据 
  4.     // 2.然后根据SEL数据找到对应的方法地址(比较耗性能但系统会有缓存) 
  5.     // 3.在根据方法地址调用对应的方法 
  6.      
  7.     [person test1]; 
  8.      
  9.     // 将方法直接包装成SEL数据类型来调用 withObject:传入的参数 
  10.     [person performSelector:@selector(test1)]; 
  11.     [person performSelector:@selector(test2:) withObject:@"传入参数"]; 

@selector

@selector 其实就是选择器,使用@selector放回SELleixing,所以SEL和@selector一般都是同时使用的。

 isMemberOfClass 用于判断是否是某个类的实例

bool flag1=[stu isMemberOfClass:[Student class]];
//stu是Student类的实例,Student为Person的子类    但是stu 不能判断为Person的实例。

isKindOfClass 判断是否为某个类的实例或者某个类子类的实例

respondsToSelector 用于判断某个类型或者对象是否有能力回应(调用)指定的方法 //就是有没有这个函数

//如果info是用+声明

 bool flag5=[per respondsToSelector:@selector(Info)];    //那结果就是NO bool flag6=[Person respondsToSelector:@selector(Info)]; //结果就是 yes
instancesRespondToSelector 用于判断某个对象的实例是否有能力回应(调用)指定的方法

//如果info是用+声明

 bool flag7=[Person instancesRespondToSelector:@selector(eat)];  //结果为yes bool flag8=[Person instancesRespondToSelector:@selector(Info)]; //结果为No
动态调用方法

使用performSelector 方法可以动态的调用其方法,如果是实例方法则调用的需要使用对象实例,而调用静态方法这需要使用对象本身。

无参数:

[stu performSelector:@selector(eat)];[Person performSelector:@selector(Info)];
有参数:
[stu performSelector:@selector(speak:) withObject:@"ddddd"];      [stu performSelector:@selector(write:andAge:) withObject:@"fasdfadaf" withObject:@"333"];

Class

    先看看Class类型的代码如下:

typedef struct objc_class *Class;typedef struct objc_object {    Class isa;} *id;

    从上面的代码可以看到Class 是结构类型,可以使用如下方式获取一个对象的Class

Class c=[Person class];

 

   @class

  由于头文件的相互包含及依赖关系,往往很小的改动就需要重新编译很多的文件。Object-C提供了一种方法可以减少由于依赖引起的重新编译@class 来告诉编译器这是一个类,编译器只需要通过指针来引用它即可,并不需要知道关于这个类的更多信息。以此来减少编译工作。

复制代码
#import <Foundation/Foundation.h>@class Person;@interface Student : NSObject{    Person *p;}@end
复制代码

0 0