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

时间:2023-03-10 08:48:29
【IOS学习】之四、协议,委托,分类粗解

何为协议,何为委托,何为分类(类别)?

委托  即 代理 delegate:

 他是 (接口的实现类)类似c中的回调。
        把某个对象要做的事情委托给别的对象去做。 那么别的对象就是这个对象的代理,来代替他处理要做的事情。
在code中,首先你要明确一个对象的委托方是谁,委托的内容是什么。
         在mfc中,每个程序都要继承自cwinapp,就是要重写几个虚函数额。
         但是在cocoa中,我们来实现个UIApplicationDelegate代理,不用继承,我们只需要考虑你要捕获的应用程序生命周期中的函数就可以了。
         可以这样用指针来看: 类a中有一个类b的指针,那么b就是a的代理委托。a干完一件事情就需要告诉b,b调用对应的方法来做出相应的响应。
         ios开发中: 如:视图之间传输信息。  两个页面uiview   来实现传值,用delegate可以很好地做到。
来看一个demo: 
  1. @interface A: UIView
  2. @property(nonatic, retain) id aValueDelegate;
  3. @end;
  4. @implementation A
  5. - (void) fa
  6. {
  7. NSString *value = @"hello";
  8. [aValueDelegate aValue:value];
  9. }
  10. @end;
  11. @interface B: UIView
  12. NSString *value;
  13. @end;
  14. @implementation B
  15. - (void) aValue:(NSString *)fromValue
  16. {
  17. value = fromValue;
  18. NSLog(@"%@", value);
  19. }
  20. @end;
  21. A *a = [[A alloc] init];
  22. B *b = [[B alloc] init];
  23. a.aValueDelegate = b;   //设置a代理委托对象为b
类别:category 主要3个功能
1、利用类别分散实现。
2、利用类别创建前向引用,实现私有函数
3、非正式协议和委托类别 
  1. @interface NSString(NumberConvenience)
  2. -(NSNumber*) lengthAsNumber;
  3. @end
协议:  类似于c++的纯虚函数(java中的接口),  只有声明,没有实现,  你需要在子类中实现。
其中@optional 属性方法不要求必须实现。   
      @required属性 要求实现协议的类必须要实现方法。
如果不确定协议是否被实现,可以使用respondsToSelector:@select()来判断。
协议不是类,就是简单定义了一个其他对象可以实现的接口。
demo是采用源哥博客(http://blog.****.net/xie376450483/article/details/7646617)的代码:
代码根据xcode的升级,有些许改动。
非正式协议:        是使用类别category来实现,他是nsobject的一个类别。这样任何类的对象都可以作为委托对象来使用。他可以列出对象能够执行的多种方法。这样用来实现委托我们可以使用选择器来判断非正式协议中是否有这个方法。 
  1. @interface NSObject (***Delegate)
  2. //method
  3. @end
  1. //
  2. //  Dog.h
  3. //  protocol2
  4. //
  5. //  Created by peter on 14-2-25.
  6. //  Copyright (c) 2014年 peter. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. @interface Dog : NSObject
  10. @property int ID;
  11. @end
  12. @interface NSObject(myCategory)
  13. - (void)callFromNSObject;
  14. @end
  15. //
  16. //  Dog.m
  17. //  protocol2
  18. //
  19. //  Created by peter on 14-2-25.
  20. //  Copyright (c) 2014年 peter. All rights reserved.
  21. //
  22. #import "Dog.h"
  23. @implementation Dog
  24. - (id)init
  25. {
  26. self = [super init];
  27. return self;
  28. }
  29. @end
  30. @implementation NSObject(myCategory)
  31. - (void)callFromNSObject
  32. {
  33. NSLog(@"iam nsobject");
  34. }
  35. @end
  36. //
  37. //  Person.h
  38. //  protocol2
  39. //
  40. //  Created by peter on 14-2-25.
  41. //  Copyright (c) 2014年 peter. All rights reserved.
  42. //
  43. #import <Foundation/Foundation.h>
  44. #import "Dog.h"
  45. @interface Person : NSObject
  46. //{
  47. //    Dog *dog;
  48. //}
  49. @property Dog *dog;
  50. - (void)callFun;
  51. @end
  52. //
  53. //  Person.m
  54. //  protocol2
  55. //
  56. //  Created by peter on 14-2-25.
  57. //  Copyright (c) 2014年 peter. All rights reserved.
  58. //
  59. #import "Person.h"
  60. @implementation Person
  61. @synthesize dog;
  62. - (void) callFun
  63. {
  64. NSLog(@"Call Fun!");
  65. [dog callFromNSObject];
  66. }
  67. @end
  68. //
  69. //  main.m
  70. //  protocol2
  71. //
  72. //  Created by peter on 14-2-25.
  73. //  Copyright (c) 2014年 peter. All rights reserved.
  74. //
  75. #import <Foundation/Foundation.h>
  76. #import "Dog.h"
  77. #import "Person.h"
  78. int main(int argc, const charchar * argv[])
  79. {
  80. @autoreleasepool {
  81. Dog *dog = [[Dog alloc]init];
  82. [dog setID:10];
  83. Person *qy = [[Person alloc]init];
  84. [qy setDog:dog];
  85. [qy callFun];
  86. }
  87. return 0;
  88. }
正式协议:一个命名方法列表。  与非正式的区别在于:他要求显示采用协议,采用协议的方法是在类的@interface声明中列出协议的名称。  这时实现协议的类应该遵守协议,承诺实现协议中的所有方法。 
  1. @protocol NSCopying
  2. -(id) copyWithZone:(NSZone *) zone;
  3. @end
  4. @interface Car : NSObject<NSCopying>
  5. {
  6. // instance variable
  7. }
  8. // method
  9. @end // Car
cocoa china中的总结:
  1.协议声明了可以被任何类实现的方法
  2.协议不是类,它是定义了一个其他对象可以实现的接口
  3.如果在某个类中实现了协议中的某个方法,也就是这个类实现了那个协议。
  4.协议经常用来实现委托对象。一个委托对象是一种用来协同或者代表其他对象的特殊对象。
  5:委托,就是调用自己定义方法,别的类来实现。
  6.新特性说明
    @optional预编译指令:表示可以选择实现的方法
    @required预编译指令:表示必须强制实现的方法 
  1. @protocol myprotocol <NSObject>
  2. @optional
  3. -(void)print:(int)value;
  4. //可选的方法
  5. @required
  6. -(int)printValue:(int)value1 andValue:(int)value2;
  7. //必须实现的
  8. @end
  9. #import <Foundation/Foundation.h>
  10. #import "myprotocol.h"
  11. //实现协议 myprotocol
  12. @interface mytest : NSObject<myprotocol>
  13. - (void)showInfo;
  14. @end
  15. #import "mytest.h"
  16. @implementation mytest
  17. -(void)showInfo
  18. {
  19. NSLog(@"I am in showInfo");
  20. }
  21. //实现协议必须实现的
  22. -(int)printValue:(int)value1 andValue:(int)value2
  23. {
  24. NSLog(@"print value1 %d,value2 %d",value1,value2);
  25. return 0;
  26. }
  27. //实现可选的
  28. -(void)print:(int)value
  29. {
  30. NSLog(@"print value is %d",value);
  31. }
  32. @end
  33. #import <Foundation/Foundation.h>
  34. #import "mytest.h"
  35. #import "myprotocol.h"
  36. int main (int argc, const charchar * argv[]) {
  37. @autoreleasepool {
  38. mytest *test=[[mytest alloc]init];
  39. [test showInfo];
  40. [test printValue:20 andValue:30];
  41. //print协议是可选的,所以在用之前一定要判断是否实现了,不然可能会出错,使用下面的方法
  42. //     [test print:20];
  43. SEL sel=@selector(print:);
  44. if([test respondsToSelector:sel]){
  45. [test print:11];
  46. }
  47. //用协议的方式实现
  48. id<myprotocol> protocol =[[[mytest alloc]init]autorelease];
  49. [protocol showInfo];
  50. [protocol printValue:200 andValue:300];
  51. if([protocol respondsToSelector:@selector(print:)]){
  52. [protocol print:111];
  53. }
  54. }
  55. return 0;
  56. }
最后看一个demo,加深理解: 
  1. //
  2. //  Dog.h
  3. //  catagory
  4. //
  5. //  Created by peter on 14-2-25.
  6. //  Copyright (c) 2014年 peter. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. @protocol dogBark;
  10. @interface Dog : NSObject
  11. {
  12. int barkCount;
  13. NSTimer *timer;
  14. }
  15. @property int ID;
  16. @property (assign)id<dogBark> delegate;     //dog master
  17. @end
  18. @protocol dogBark <NSObject>
  19. - (void)bark: (Dog*)thisDog count:(int)count;
  20. @end
  21. //
  22. //  Dog.m
  23. //  catagory
  24. //
  25. //  Created by peter on 14-2-25.
  26. //  Copyright (c) 2014年 peter. All rights reserved.
  27. //
  28. #import "Dog.h"
  29. @implementation Dog
  30. //ID use _ID
  31. @synthesize delegate;
  32. - (id)init
  33. {
  34. if (self = [super init]) {
  35. //create nstimer user, 1.0s use updateTimer:nil
  36. timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];
  37. }
  38. return self;
  39. }
  40. - (void) updateTimer:(id)arg
  41. {
  42. barkCount++;
  43. NSLog(@"dog bar %d", barkCount);
  44. //user master delegate  bark:count
  45. [delegate bark:self count:barkCount];
  46. }
  47. @end
  48. //
  49. //  person.h
  50. //  catagory
  51. //
  52. //  Created by peter on 14-2-25.
  53. //  Copyright (c) 2014年 peter. All rights reserved.
  54. //
  55. #import <Foundation/Foundation.h>
  56. #import "Dog.h"
  57. @interface person : NSObject<dogBark>
  58. {
  59. Dog *_dog;
  60. }
  61. @property (retain, nonatomic) Dog *dog;
  62. @end
  63. //
  64. //  person.m
  65. //  catagory
  66. //
  67. //  Created by peter on 14-2-25.
  68. //  Copyright (c) 2014年 peter. All rights reserved.
  69. //
  70. #import "person.h"
  71. @implementation person
  72. - (void)setDog:(Dog *)aDog
  73. {
  74. if (_dog != aDog) {
  75. [_dog setDelegate:self];
  76. }
  77. }
  78. //dog use person interface
  79. - (void)bark:(Dog *)thisDog count:(int)count
  80. {
  81. NSLog(@"person bark: this dog %d bark %d", [thisDog ID], count);
  82. }
  83. @end
  84. //
  85. //  main.m
  86. //  catagory
  87. //
  88. //  Created by peter on 14-2-25.
  89. //  Copyright (c) 2014年 peter. All rights reserved.
  90. //
  91. #import <Foundation/Foundation.h>
  92. #import "Dog.h"
  93. #import "person.h"
  94. int main(int argc, const charchar * argv[])
  95. {
  96. @autoreleasepool {
  97. person *qy = [[person alloc]init];
  98. Dog *dog = [[Dog alloc]init];
  99. [dog setID:10];
  100. [qy setDog:dog];
  101. while (1) {
  102. [[NSRunLoop currentRunLoop]run];
  103. }
  104. }
  105. return 0;
  106. }

解释一下循环:

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