OC协议和接口和协议有哪些的区别

iOS- OC夯实基础之类目 延展 协议 - 简书
iOS- OC夯实基础之类目 延展 协议
类目 (category)
对现有的类添加扩展,如:系统中的类,在类目中添加的方法会被子类继承,而且运行时跟其他的方法没有区别。
作为子类的替代方式,不需要定义和使用一个子类,可以通过类目直接向已有的类目里添加方法。
对类中的方法进行归类,利用categopry把一个庞大的类划分为小块来分别进行开发,从而更好地对类中的方法进行更新和维护。通过类目添加的方法会成为原始类 的一部分
当然也有使用Category是需要注意的问题:
Category可以访问原始类的实例变量,但不能添加实例变量,如果想添加变量,那就通过继承创建子类来实现,或者利用runtime实现。
Category可以重载原始类的方法,这样会覆盖掉原始类的方法。如果确实要重载,那就通过继承创建子类来实现。
和普通接口有所区别的是,在Category的实现文件中的实例方法只要你不去调用它你可以不用实现所有声明的所有方法。
命名方式: 类名+扩展方法,如“UIAlertView+AFNetworking”。类目的接口声明与类的定义十分相似,但类目不继承父类,只需要带有一个括号,表明该类目的主要用 途。
Category 与SubClass 区别
只能为类添加方法
既能为类添加方法,又能添加属性
新添加的方法会成为原始类的一部分,能被子类继承
新添加的方法只有子类才有,父类不具有,子类才能调用
类目.h文件
#import &Foundation/Foundation.h&
在类目中不能添加实例变量
@interface NSString (CSayHi)
-(void)sayHi;//类目的方法
类目.m文件
#import "NSString+CSayHi.h"
@implementation NSString (CSayHi)
-(void)sayHi{//类目方法的实现
NSLog(@"这是类目提供的方法,字符内容是%@",self);
#import &UIKit/UIKit.h&
#import "NSString+CSayHi.h"
- (void)viewDidLoad {
[super viewDidLoad];
NSString *str=@"hello";//定义一个字符串对象并赋值
[str sayHi];//调用类目方法
延展 (Extension)
延展是特殊形式的类目
延展中定义的方法在类本身中实现
延展写在.m文件上
延展不提供名称表示方法必须实现,提供名称可以不实现
定义类的私有方法,管理类的私有方法
形式和类目相同,不用新创建文件,只是把类目的interface地方的文件放在了你需要扩展的类的.m文件里边。
#import "Student.h"
@interface Student (extension)//为Student类创建一个私有的方法text
@implementation Student
-(void)text
NSLog(@"你好");
外界 [student hello]的时候就会打印出“你好”。但是在外界不能调用text方法,[student text]是不对的。只能在.m文件里边通过self来调用私有方法text。隐藏了内部的实现。
协议 (protocol)
概念:协议(protocol)是Objective-c中一个非常重要的语言特性. 一个协议其实就是一系列有关联的方法的集合。协议中的方法并不是由协议本身去实现,相反而是由遵循这个协议的其他类来实现。
// OC的协议由@protocol声明的一组方法列表,要求其他的类去实现,
//相当于@interface部分的声明
@protocol xxxDelegate
//必须实现的协议方法
//可选实现
相关代码自己百度.
为什么要使用协议:
苹果的官方文档指出三个原因:
To declare methods that others are expected to implement
To declare the interface to an object while concealing its class
To capture similarities among classes that are not hierarchically related
其实还有第4个很重要的原因,那就是减少继承类的复杂性。
一个经典的例子就是iOS UI框架里面的UITableViewController类。假如没有“协议”功能,用户就必须选择用继承和重载接口的方法来实现复杂的UI控制以及其他事件的处理——这就对基类的设计提出了更大的挑战了。对于像这样一个table view,一个很好的实现方法就是采用协议,由协议里的接口来控制不同的数据源以及各种复杂的用户操作。UIKit中设计了两个很好的协议UITableViewDelegate,UITableViewDataSource来实现UITableViewController的控制。任何遵循这两个协议的类都可以实现对UITableView的控制。
代理与协议的区别:
代理是一种设计模式概念,协议是一种技术,代理是用协议来实现的.代理是2个对象之间通讯的一种方式。 代理主要做反向传值的。实现系统的一些回调方法.
至于代理的详细信息,不是本篇的重点,足可以另开一篇文章详谈了.
今天就到这.
1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch框架 3.Xcode使用 -------------------- CocoaTouch Media Core Services Core OS -------...
block 虽然很早就学习过block方面的知识,但一直没怎么用过,说明自己还是个菜鸟中的菜鸟,看到大牛们的代码优雅又简洁,各种炫酷的功能很多都有block的影子,所以下决心好好学习这方面的内容.以后有关于block中的所有问题都会总结在这里,方便加深对OC中block的理...
父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。o 深拷贝同浅拷贝的区别:浅拷贝是指针拷贝,对一个对象进行浅拷贝,相当于对指向对象的指针进行复制,产生一个新的指向这个对象的指针,那么就是有两个指针指向同一个对象,这个对象销毁后两个指针都应...
o 深拷贝同浅拷贝的区别:浅拷贝是指针拷贝,对一个对象进行浅拷贝,相当于对指向对象的指针进行复制,产生一个新的指向这个对象的指针,那么就是有两个指针指向同一个对象,这个对象销毁后两个指针都应该置空。深拷贝是对一个对象进行拷贝,相当于对对象进行复制,产生一个新的对象,那么就有...
下面是我最近两年学习OC中的一些基础知识,对于学习OC基础知识的人可能有些帮助,拿出来分享一下,还是那句话不喜勿喷哦亲。。。。。 (1) 一、Objective-C概述 1. Object-C简称OC,扩充自C语言的面向对象编程语言 2. 苹果OS X和iOS操作系统的主要...
大家好,欢迎来到实验中学初二一班播报空间我是播报员张柏钰。今天我推荐的书是《骆驼祥子》,《骆驼祥子》讲述的是旧中国北平城里一个人力车夫祥子的悲惨故事。日益凋敝的的农村使他无法生存下去,他来到城市,渴望以自己的诚实劳动创立新的生活,他尝试过各种工作,最后选中拉洋车,祥子是一个...
此刻,我坐在电脑前敲打着这篇文字的时候,透过打开的窗户,我看到了小区里温暖的灯火,听到了孩子奔跑追逐的欢笑,看到了在阳台上收拾衣物的慈祥的老人,这个永恒美好的世界。同时,我又想起在大凉山上的那些日日夜夜,那些深邃的没有光亮的黑夜,那些泥泞陡峭的山路,那些简单纯朴的彝族同胞,...
如果末日将要来临,你希望怎么做?假如希望多活3年,我们看应该怎么准备。 工程问题:为什么是3年?大约1001夜后,地球表面才可能重新适合人类生活。 首先要有一个居住的地方 这个地方应该地下、山洞,至少10米深度,能防辐射最好。这个地洞最好用水泥墙体加固。 工程问题:需要多大...
今天是我第一天来简书写文章,其实我的职业是一个程序猿,所以我的文字功底并不是很好。当然我却是一个喜欢看书和分享的人。我觉得文字可以很好的表达自己内心的一些想法,文字并不是冷冰冰的,它是有感情的。 1 在我儿时的时候,我其实是有一个梦想的,我希望自己能成为像鲁迅那样的人,通过...
家是用来存放爱的地方,不是用来讲理的地方。 每一个家庭,都不可避免的面临着婚姻的磨合期,审美疲劳期等情感方面的危机期。 无论你们婚前是怎样的相亲相爱,怎样的难分难舍,怎样的海誓山盟,都将经历这样的婚姻里程碑,甚至白雪公主和她的王子也要走过这样的路程。 大仲马曾说:“要维持一...51CTO旗下网站
详解Objective-C中委托和协议
Objective-C委托和协议本没有任何关系,协议如前所述,就是起到C++中纯虚类的作用,对于“委托”则和协议没有关系,只是我们经常利用协议还实现委托的机制,其实不用协议也完全可以实现委托。
作者:佚名来源:互联网| 14:32
Objective-C中委托和协议是本文要介绍的内容,委托和协议是两个概念,协议实际上相当于中的纯虚类的概念,只定义并只能由其它类来实现。而委托类似于Java中的接口。(Objective-C实现委托这种机制是利用协议来实现的,这种说法我现在认为是不对的,理由下述:)。
Objective-C委托和协议本没有任何关系,协议如前所述,就是起到中纯虚类的作用,对于&委托&则和协议没有关系,只是我们经常利用协议还实现委托的机制,其实不用协议也完全可以实现委托。下面说明了实现方式:
定义一个类A:
@interface&A:NSObject &-(void) &@end &@implement&A &-(void)print{ &} &@end&
定义一个类B,在B中定义类A的实例为B中的成员变量:
@interface&B:NSObject{ &&&&&&&&A&*a_ &} &@end&
下面在mai()函数中实现委托机制:
void&main() &{ &B&*b=[[B&alloc]init]; &A&*a=[[A&alloc]init]; &b.a_delegate=a; &[b.a_delegate&print]; &}&
这样,最基本的委托机制就完成了,套用最通俗的一句解释:B需要完成一个print的操作,但他自己并没有实现这个操作,而是交给了A去完成,自己只是在需要时调用A中实现的print操作。
下面再写一种实现方式,这样方式更接近于我们通常见到的用协议还实现的方式:
我们还是定义一个类A:
@interface&A:NSObject{ &B&*b; &} &-(void) &@end &@implement&A &@synasize& &-(void)viewDidLoad{ &b=[[B&alloc]init]; &b.delegate=self; &} &-(void)print{ &NSLog(@&print&was&called&); &} &@end&
然后类B的定义改成如下所示:
@interface&B:NSObject{ &id&delegate &} &@propert(nonamtic,retain)&id& &@end &&现在我们不用main()函数,在B的实现部分来实现委托机制: &&@implement&B &-(void)callPrint{ &[self.delegate&print]; &} &@end&
上面这种实现方式和第一种其实是一样的,只是第一种是在第三方函数调用委托方法。delegate是id类型,本例中就是A类的一个实例,当然可以调用A类中的print。第二种方式不存在第三方函数,是在B类中调用 A类中的方法。或者说,B中需要print方法,自己不实现,让A来实现,自己调用 。
再接下来就是最常见的用协议实现委托的方式,说明如下:
protocol-协议,就是使用了这个协议后就要按照这个协议来办事,协议要求实现的方法就一定要实现。
delegate-委托,顾名思义就是委托别人办事,就是当一件事情发生后,自己不处理,让别人来处理。
当一个A view 里面包含了B view
b view需要修改a view界面,那么这个时候就需要用到委托了。
需要几个步骤
1、首先定一个协议
2、a view实现协议中的方法
3、b view设置一个委托变量
4、把b view的委托变量设置成a view,意思就是 ,b view委托a view办事情。
5、事件发生后,用委托变量调用a view中的协议方法
B_View.h: &@protocol&UIBViewDelegate&&@optional &-&(void)ontouch:(UIScrollView&*)scrollV&//声明协议方法 &@end &@interface&BView&:&UIScrollView&{ &id&&&_&//设置委托变量 &} &@property(nonatomic,assign)&id&&&_& &@end &B_View.mm: &@synthesize&_ &-&(id)initWithFrame:(CGRect)frame&{ &if&(self&=&[super&initWithFrame:frame])&{ &//&Initialization&code &_touchdelegate=nil; &} &return& &} &-&(void)&touchesBegan:(NSSet*)touches&withEvent:(UIEvent*)event &{ &[super&touchesBegan:touches&withEvent:event]; &if(_touchdelegate!=nil&&&&[_touchdelegate&respondsToSelector:&@selector(ontouch:)&]&==&true)& &[_touchdelegate&ontouch:self];&//调用协议委托 &} &&@end &A_View.h: &@interface&AViewController&:&UIViewController&&&&{ &BView&*m_BV &} &@end &A_View.mm: &-&(void)viewWillAppear:(BOOL)animated &{ &m_BView._touchdelegate&=&self;&//设置委托 &[self.view&addSubview:&m_BView]; &} &-&(void)ontouch:(UIScrollView&*)scrollView &{ &&&&//实现协议 &}&
小结:详解Objective-C中委托和协议的内容介绍完了,希望通过本本文的学习能对你有所帮助!【编辑推荐】【责任编辑: TEL:(010)】
大家都在看猜你喜欢
头条热点关注头条热点
24H热文一周话题本月最赞
讲师:305377人学习过
讲师:251982人学习过
讲师:15561人学习过
精选博文论坛热帖下载排行
本书分为8章。第1章主要对XML做了简单的介绍。第2章详细讲解规范的XML文件。第3章主要讲解有效的XML文件,特别重点讲解DTD文件。第4章讲解C...
订阅51CTO邮刊Posts - 79,
Articles - 0,
Comments - 1691
CODING 完美世界...
09:52 by KenshinCui, ... 阅读,
概述 ObjC的语法主要基于smalltalk进行设计的,除了提供常规的面向对象特性外,还增加了很多其他特性,这一节将重点介绍ObjC中一些常用的语法特性。当然这些内容虽然和其他高级语言命名不一样,但是我们都可以在其中找到他们的影子,在文章中我也会对比其他语言进行介绍,这一节的重点内容如下:
协议protocol 在ObjC中使用@protocol定义一组方法规范,实现此协议的类必须实现对应的方法。熟悉面向对象的童鞋都知道接口本身是对象行为描述的协议规范。也就是说在ObjC中@protocol和其他语言的接口定义是类似的,只是在ObjC中interface关键字已经用于定义类了,因此它不会再像C#、Java中使用interface定义接口了。 假设我们定义了一个动物的协议AnimalDelegate,人员Person这个类需要实现这个协议,请看下面的代码: AnimalDelegate.h//
AnimalDelegate.h
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//定义一个协议
@protocol AnimalDelegate &NSObject&
@required //必须实现的方法
@optional //可选实现的方法
Person.h//
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
#import "AnimalDelegate.h"
@interface Person : NSObject&AnimalDelegate&
Person.m//
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import "Person.h"
@implementation Person
-(void)eat{
NSLog(@"eating...");
这里需要说明几点:
一个协议可以扩展自另一个协议,例如上面AnimalDelegate就扩展自NSObject,如果需要扩展多个协议中间使用逗号分隔;
和其他高级语言中接口不同的是协议中定义的方法不一定是必须实现的,我们可以通过关键字进行@required和@optional进行设置,如果不设置则默认是@required(注意ObjC是弱语法,即使不实现必选方法编译运行也不会报错);
协议通过&&进行实现,一个类可以同时实现多个协议,中间通过逗号分隔;
协议的实现只能在类的声明上,不能放到类的实现上(也就是说必须写成@interface Person:NSObject&AnimalDelegate&而不能写成@implementation Person&AnimalDelegate&);
协议中不能定义属性、成员变量等,只能定义方法;
事实上在ObjC中协议的更多作用是用于约束一个类必须实现某些方法,而从面向对象的角度而言这个类跟接口并不一定存在某种自然关系,可能是两个完全不同意义上的事物,这种模式我们称之为代理模式(Delegation)。在Cocoa框架中大量采用这种模式实现数据和UI的分离,而且基本上所有的协议都是以Delegate结尾。
现在假设需要设计一个按钮,我们知道按钮都是需要点击的,在其他语言中通常会引入事件机制,只要使用者订阅了点击事件,那么点击的时候就会触发执行这个事件(这是对象之间解耦的一种方式:代码注入)。但是在ObjC中没有事件的定义,而是使用代理来处理这个问题。首先在按钮中定义按钮的代理,同时使用协议约束这个代理(事件的触发者)必须实现协议中的某些方法,当按钮处理过程中查看代理是否实现了这个方法,如果实现了则调用这个方法。
KCButton.h//
KCButton.h
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
@class KCB
//一个协议可以扩展另一个协议,例如KCButtonDelegate扩展了NSObject协议
@protocol KCButtonDelegate &NSObject&
@required //@required修饰的方法必须实现
-(void)onClick:(KCButton *)
@optional //@optional修饰的方法是可选实现的
-(void)onMouseover:(KCButton *)
-(void)onMouseout:(KCButton *)
@interface KCButton : NSObject
#pragma mark - 属性
#pragma mark 代理属性,同时约定作为代理的对象必须实现KCButtonDelegate协议
@property (nonatomic,retain) id&KCButtonDelegate& delegate;
#pragma mark - 公共方法
#pragma mark 点击方法
KCButton.m//
KCButton.m
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import "KCButton.h"
@implementation KCButton
-(void)click{
NSLog(@"Invoke KCButton's click method.");
//判断_delegate实例是否实现了onClick:方法(注意方法名是"onClick:",后面有个:)
//避免未实现ButtonDelegate的类也作为KCButton的监听
if([_delegate respondsToSelector:@selector(onClick:)]){
[_delegate onClick:self];
MyListener.h//
MyListener.h
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
@class KCB
@protocol KCButtonD
@interface MyListener : NSObject&KCButtonDelegate&
-(void)onClick:(KCButton *)
MyListener.m//
MyListener.m
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import "MyListener.h"
#import "KCButton.h"
@implementation MyListener
-(void)onClick:(KCButton *)button{
NSLog(@"Invoke MyListener's onClick method.The button is:%@.",button);
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
#import "KCButton.h"
#import "MyListener.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
KCButton *button=[[KCButton alloc]init];
MyListener *listener=[[MyListener alloc]init];
button.delegate=
[button click];
Invoke KCButton's click method.
Invoke MyListener's onClick method.The button is:&KCButton: 0x&.
我们通过例子模拟了一个按钮的点击过程,有点类似于Java中事件的实现机制。通过这个例子我们需要注意以下几点内容:
id可以表示任何一个ObjC对象类型,类型后面的”&协议名&“用于约束作为这个属性的对象必须实现该协议(注意:使用id定义的对象类型不需要加“*”);
MyListener作为事件触发者,它实现了KCButtonDelegate代理(在ObjC中没有命名空间和包的概念,通常通过前缀进行类的划分,“KC”是我们自定义的前缀)
在.h文件中如果使用了另一个文件的类或协议我们可以通过@class或者@protocol进行声明,而不必导入这个文件,这样可以提高编译效率(注意有些情况必须使用@class或@protocol,例如上面KCButton.h中上面声明的KCButtonDelegate协议中用到了KCButton类,而此文件下方的KCButton类声明中又使用了KCButtonDelegate,从而形成在一个文件中互相引用关系,此时必须使用@class或者@protocol声明,否则编译阶段会报错),但是在.m文件中则必须导入对应的类声明文件或协议文件(如果不导入虽然语法检查可以通过但是编译链接会报错);
使用respondsToSelector方法可以判断一个对象是否实现了某个方法(需要注意方法名不是”onClick”而是“onClick:”,冒号也是方法名的一部分);
属性中的(nonatomic,retain)不是这篇文章的重点,在接下来的文章中我们会具体介绍。
代码块Block
在C#异步编程时我们经常进行函数回调,由于函数调用是异步执行的,我们如果想让一个操作执行完之后执行另一个函数,则无法按照正常代码书写顺序进行编程,因为我们无法获知前一个方法什么时候执行结束,此时我们经常会用到匿名委托或者lambda表达式将一个操作作为一个参数进行传递。其实在ObjC中也有类似的方法,称之为代码块(Block)。Block就是一个函数体(匿名函数),它是ObjC对于闭包的实现,在块状中我们可以持有或引用局部变量(不禁想到了lambda表达式),同时利用Block你可以将一个操作作为一个参数进行传递(是不是想起了C语言中的函数指针)。在下面的例子中我们将使用Block实现上面的点击监听操作:
KCButton.h//
KCButton.h
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
@class KCB
typedef void(^KCButtonClick)(KCButton *);
@interface KCButton : NSObject
#pragma mark - 属性
#pragma mark 点击操作属性
@property (nonatomic,copy) KCButtonClick onC
//上面的属性定义等价于下面的代码
//@property (nonatomic,copy) void(^ onClick)(KCButton *);
#pragma mark - 公共方法
#pragma mark 点击方法
KCButton.m//
KCButton.m
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import "KCButton.h"
@implementation KCButton
-(void)click{
NSLog(@"Invoke KCButton's click method.");
if (_onClick) {
_onClick(self);
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
#import "KCButton.h"
int main(int argc, const char * argv[]) {
KCButton *button=[[KCButton alloc]init];
button.onClick=^(KCButton *btn){
NSLog(@"Invoke onClick method.The button is:%@.",btn);
[button click];
Invoke KCButton's click method.
Invoke onClick method.The button is:&KCButton: 0x&.
上面代码中使用Block同样实现了按钮的点击事件,关于Block总结如下:
Block类型定义:返回值类型(^ 变量名)(参数列表)(注意Block也是一种类型);
Block的typedef定义:返回值类型(^类型名称)(参数列表);
Block的实现:^(参数列表){操作主体};
Block中可以读取块外面定义的变量但是不能修改,如果要修改那么这个变量必须声明_block修饰;
分类Category
当我们不改变原有代码为一个类扩展其他功能时我们可以考虑继承这个类进行实现,但是这样一来使用时就必须定义成新实现的子类才能拥有扩展的新功能。如何在不改变原有类的情况下扩展新功能又可以在使用时不必定义新类型呢?我们知道如果在C#中可以使用扩展方法,其实在ObjC中也有类似的实现,就是分类Category。利用分类,我们就可以在ObjC中动态的为已有类添加新的行为(特别是系统或框架中的类)。在C#中字符串有一个Trim()方法用于去掉字符串前后的空格,使用起来特别方便,但是在ObjC中却没有这个方法,这里我们不妨通过Category给NSString添加一个stringByTrim()方法:
NSString+Extend.h//
NSString+Extend.h
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
@interface NSString (Extend)
-(NSString *)stringByT
NSString+Extend.m//
NSString+Extend.m
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import "NSString+Extend.h"
@implementation NSString (Extend)
-(NSString *)stringByTrim{
NSCharacterSet *character= [NSCharacterSet whitespaceCharacterSet];
return [self stringByTrimmingCharactersInSet:character];
Protocol&Block&Category
Created by Kenshin Cui on 14-2-2.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
#import "NSString+Extend.h"
int main(int argc, const char * argv[]) {
NSString *name=@" Kenshin Cui ";
name=[name stringByTrim];
NSLog(@"I'm %@!",name); //结果:I'm Kenshin Cui!
通过上面的输出结果我们可以看出已经成功将@” Kenshin Cui ”两端的空格去掉了。分类文件名一般是“原有类名+分类名称”,分类的定义是通过在原有类名后加上”(分类名)”来定义的(注意声明文件.h和实现文件.m都是如此)。268被浏览51,065分享邀请回答344 条评论分享收藏感谢收起416 条评论分享收藏感谢收起

我要回帖

更多关于 接口和协议有哪些 的文章

 

随机推荐