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

【IOS学习】之四、协议,委托,分类粗解

2014-02-26 09:38 281 查看
何为协议,何为委托,何为分类(类别)?

委托  即 代理 delegate:

 他是 (接口的实现类)类似c中的回调。

        把某个对象要做的事情委托给别的对象去做。 那么别的对象就是这个对象的代理,来代替他处理要做的事情。
在code中,首先你要明确一个对象的委托方是谁,委托的内容是什么。

         在mfc中,每个程序都要继承自cwinapp,就是要重写几个虚函数额。
         但是在cocoa中,我们来实现个UIApplicationDelegate代理,不用继承,我们只需要考虑你要捕获的应用程序生命周期中的函数就可以了。
         可以这样用指针来看: 类a中有一个类b的指针,那么b就是a的代理委托。a干完一件事情就需要告诉b,b调用对应的方法来做出相应的响应。

         ios开发中: 如:视图之间传输信息。  两个页面uiview   来实现传值,用delegate可以很好地做到。

来看一个demo:
@interface A: UIView

@property(nonatic, retain) id aValueDelegate;

@end;

@implementation A

- (void) fa
{
NSString *value = @"hello";
[aValueDelegate aValue:value];
}

@end;

@interface B: UIView
NSString *value;
@end;

@implementation B

- (void) aValue:(NSString *)fromValue
{
value = fromValue;
NSLog(@"%@", value);
}

@end;

A *a = [[A alloc] init];
B *b = [[B alloc] init];
a.aValueDelegate = b;   //设置a代理委托对象为b


类别:category 主要3个功能
1、利用类别分散实现。
2、利用类别创建前向引用,实现私有函数
3、非正式协议和委托类别

@interface NSString(NumberConvenience)
-(NSNumber*) lengthAsNumber;
@end


协议:  类似于c++的纯虚函数(java中的接口),  只有声明,没有实现,  你需要在子类中实现。
其中@optional 属性方法不要求必须实现。   
      @required属性 要求实现协议的类必须要实现方法。

如果不确定协议是否被实现,可以使用respondsToSelector:@select()来判断。
协议不是类,就是简单定义了一个其他对象可以实现的接口。

demo是采用源哥博客(http://blog.csdn.net/xie376450483/article/details/7646617)的代码:
代码根据xcode的升级,有些许改动。

非正式协议:        是使用类别category来实现,他是nsobject的一个类别。这样任何类的对象都可以作为委托对象来使用。他可以列出对象能够执行的多种方法。这样用来实现委托我们可以使用选择器来判断非正式协议中是否有这个方法。
@interface NSObject (***Delegate)
//method
@end

//
//  Dog.h
//  protocol2
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Dog : NSObject

@property int ID;

@end

@interface NSObject(myCategory)

- (void)callFromNSObject;

@end

//
//  Dog.m
//  protocol2
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import "Dog.h"

@implementation Dog

- (id)init
{
self = [super init];
return self;
}

@end

@implementation NSObject(myCategory)

- (void)callFromNSObject
{
NSLog(@"iam nsobject");
}

@end

//
//  Person.h
//  protocol2
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Dog.h"

@interface Person : NSObject
//{
//    Dog *dog;
//}

@property Dog *dog;

- (void)callFun;

@end

//
//  Person.m
//  protocol2
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import "Person.h"

@implementation Person

@synthesize dog;

- (void) callFun
{
NSLog(@"Call Fun!");
[dog callFromNSObject];
}

@end

//
//  main.m
//  protocol2
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Dog.h"
#import "Person.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
Dog *dog = [[Dog alloc]init];
[dog setID:10];
Person *qy = [[Person alloc]init];
[qy setDog:dog];
[qy callFun];
}
return 0;
}

正式协议:一个命名方法列表。  与非正式的区别在于:他要求显示采用协议,采用协议的方法是在类的@interface声明中列出协议的名称。
 这时实现协议的类应该遵守协议,承诺实现协议中的所有方法。

@protocol NSCopying
-(id) copyWithZone:(NSZone *) zone;
@end

@interface Car : NSObject<NSCopying>
{
// instance variable
}
// method
@end // Car


cocoa china中的总结:
  1.协议声明了可以被任何类实现的方法
  2.协议不是类,它是定义了一个其他对象可以实现的接口
  3.如果在某个类中实现了协议中的某个方法,也就是这个类实现了那个协议。
  4.协议经常用来实现委托对象。一个委托对象是一种用来协同或者代表其他对象的特殊对象。
  5:委托,就是调用自己定义方法,别的类来实现。
  6.新特性说明
    @optional预编译指令:表示可以选择实现的方法
    @required预编译指令:表示必须强制实现的方法

@protocol myprotocol <NSObject>
@optional
-(void)print:(int)value;
//可选的方法

@required
-(int)printValue:(int)value1 andValue:(int)value2;
//必须实现的

@end

#import <Foundation/Foundation.h>
#import "myprotocol.h"
//实现协议 myprotocol
@interface mytest : NSObject<myprotocol>
- (void)showInfo;
@end

#import "mytest.h"

@implementation mytest
-(void)showInfo
{
NSLog(@"I am in showInfo");
}

//实现协议必须实现的
-(int)printValue:(int)value1 andValue:(int)value2
{
NSLog(@"print value1 %d,value2 %d",value1,value2);
return 0;
}

//实现可选的
-(void)print:(int)value
{
NSLog(@"print value is %d",value);
}

@end

#import <Foundation/Foundation.h>
#import "mytest.h"
#import "myprotocol.h"

int main (int argc, const char * argv[]) {
@autoreleasepool {
mytest *test=[[mytest alloc]init];
[test showInfo];
[test printValue:20 andValue:30];
//print协议是可选的,所以在用之前一定要判断是否实现了,不然可能会出错,使用下面的方法
//     [test print:20];
SEL sel=@selector(print:);
if([test respondsToSelector:sel]){
[test print:11];
}

//用协议的方式实现
id<myprotocol> protocol =[[[mytest alloc]init]autorelease];
[protocol showInfo];
[protocol printValue:200 andValue:300];
if([protocol respondsToSelector:@selector(print:)]){
[protocol print:111];
}
}
return 0;
}


最后看一个demo,加深理解:
//
//  Dog.h
//  catagory
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import <Foundation/Foundation.h>

@protocol dogBark;

@interface Dog : NSObject
{
int barkCount;
NSTimer *timer;
}

@property int ID;
@property (assign)id<dogBark> delegate;     //dog master

@end

@protocol dogBark <NSObject>

- (void)bark: (Dog*)thisDog count:(int)count;

@end

//
//  Dog.m
//  catagory
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import "Dog.h"

@implementation Dog

//ID use _ID
@synthesize delegate;

- (id)init
{
if (self = [super init]) {
//create nstimer user, 1.0s use updateTimer:nil
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];

}
return self;
}

- (void) updateTimer:(id)arg
{
barkCount++;
NSLog(@"dog bar %d", barkCount);

//user master delegate  bark:count
[delegate bark:self count:barkCount];
}

@end

//
//  person.h
//  catagory
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Dog.h"

@interface person : NSObject<dogBark>
{
Dog *_dog;
}

@property (retain, nonatomic) Dog *dog;

@end

//
//  person.m
//  catagory
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import "person.h"

@implementation person

- (void)setDog:(Dog *)aDog
{
if (_dog != aDog) {
[_dog setDelegate:self];
}
}

//dog use person interface
- (void)bark:(Dog *)thisDog count:(int)count
{
NSLog(@"person bark: this dog %d bark %d", [thisDog ID], count);
}

@end

//
//  main.m
//  catagory
//
//  Created by peter on 14-2-25.
//  Copyright (c) 2014年 peter. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Dog.h"
#import "person.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
person *qy = [[person alloc]init];
Dog *dog = [[Dog alloc]init];
[dog setID:10];
[qy setDog:dog];

while (1) {
[[NSRunLoop currentRunLoop]run];
}
}
return 0;
}


解释一下循环:

 [[NSRunLoop currentRunLoop]run];
 run是一种cocoa构造,一直处于阻塞状态, 知道某些事情发生未知。
run循环等待用户事件的时候,将一直保持运行而不会返回。

-----jofranks 2014.2.26 于北京
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: