1.你有没有用到过分类?怎么用?
类别(category)是Objective-C的一项功能,可扩展类的接口,而无需对类进行子类化,我们可以在不知道某个类内部实现的情况下,为该类增加方法。如果我们想增加某个框架(framework)中的类的方法,category 就非常有效。类别并不能为类声明新的实例变量,他只包含方法。然而在类作用域内所有实例变量,都能被这些类别访问。他们包括为类声明的所有的实例变量,甚至那些被@private 修饰的变量。可以为一个类添加多个类别,但每个类别名必须不同,而且每个类别都必须声明并实现一套不同的方法。
我们通过 category 来修改一个类的时候,他对应用程序里这个类所有对象都起作用。跟子类不一样,category 不能增加成员变量。我们还可以用 category里重写类原先存在的方法(但是并不推荐这么做)。
可以将类别作为一种手段,对头文件中的相关方法声明进行分组,甚至还可以将不同的类别声明放在不同的头文件中,框架在其所有的头文件中使用这些技巧达到清晰明确的效果,还可以使用称为类别扩展的匿名类别,在实现文件(.m)文件中声明专有的属性和专有的方法。
类别主要有3个作用:
(1)将类的实现分散到多个不同文件或多个不同框架中。
(2)创建对私有方法的前向引用。
(3)向对象添加非正式协议。
继承可以增加,修改或者删除方法,并且可以增加属性。
下面是经常用的一个Category。
//UIView+Extension.h
#import <UIKit/UIKit.h>
@interface UIView (Extension)//括号中的是分类的名字
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@property (nonatomic, assign) CGFloat maxX;
@property (nonatomic, assign) CGFloat maxY;
@property (nonatomic, assign) CGFloat centerX;
@property (nonatomic, assign) CGFloat centerY;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGSize size;
@end
//UIView+Extension.m
#import "UIView+Extension.h"
@implementation UIView (Extension)
- (void)setX:(CGFloat)x
{
CGRect frame = self.frame;
frame.origin.x = x;
self.frame = frame;
}
- (CGFloat)x
{
return self.frame.origin.x;
}
- (void)setMaxX:(CGFloat)maxX
{
self.x = maxX - self.width;
}
- (CGFloat)maxX
{
return CGRectGetMaxX(self.frame);
}
- (void)setMaxY:(CGFloat)maxY
{
self.y = maxY - self.height;
}
- (CGFloat)maxY
{
return CGRectGetMaxY(self.frame);
}
- (void)setY:(CGFloat)y
{
CGRect frame = self.frame;
frame.origin.y = y;
self.frame = frame;
}
- (CGFloat)y
{
return self.frame.origin.y;
}
- (void)setCenterX:(CGFloat)centerX
{
CGPoint center = self.center;
center.x = centerX;
self.center = center;
}
- (CGFloat)centerX
{
return self.center.x;
}
- (void)setCenterY:(CGFloat)centerY
{
CGPoint center = self.center;
center.y = centerY;
self.center = center;
}
- (CGFloat)centerY
{
return self.center.y;
}
- (void)setWidth:(CGFloat)width
{
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
- (CGFloat)width
{
return self.frame.size.width;
}
- (void)setHeight:(CGFloat)height
{
CGRect frame = self.frame;
frame.size.height = height;
self.frame = frame;
}
- (CGFloat)height
{
return self.frame.size.height;
}
- (void)setSize:(CGSize)size
{
CGRect frame = self.frame;
frame.size = size;
self.frame = frame;
}
- (CGSize)size
{
return self.frame.size;
}
@end
延展(Extension)是“匿名”的类目,延展定义类的私有方法,一般是在类的实现文件@implementation之上定义如:Person() 和类目的区别在于括号里面是空的,没有名字的,暂时性的存在,只能本类调用方法,子类也无法调用父类的延展
另外在本类的实现文件@implementation之上也可以定义私有方法,私有的静态变量
延展的特点就是定义私有方法
// extension
@interface MyObject()
{
int iextension;
}
-(void)testInExtension;// 类的mainimplementation不实现的话,有编译警告。
@end
// category
@interface MyObject(categoryDemo)
{
// int icategory; // error: Ivarsmay not be placed in categories
}
-(void)testInCategory;// 不强制要求在类的mainimplementation中实现
@end
他们的主要区别是:
1、形式上来看,extension可以认为是私有的category。
2、extension里声明的方法需要在mainimplementation中实现,category不强制要求。
3、extension可以添加属性(变量),category不可以。
2说一说协议?
协议(Protocol)
没有父类也不能定义实例变量,只声明方法,声明未知类的接口,两个类之间的通信
@required :必须实现。默认
@optional :选择性的实现
NSObject为基本类根类也为基协议,可以写也可以不写。
因为IOS中不可以多继承,所以可以通过Protocol委托代理,实现多个接口来实现多继承。
委托(Delegate)
delegate中文叫做委托,通常会用在class内部把一些事件处理”委托”给别人去完成。
Delegate本身应该称为一种设计模式,是把一个类自己需要做的一部分事情,让另一个类(也可以就是自己本身)来完成,而实际做事的类为delegate。而protocol是一种语法,它的主要目标是提供接口给遵守协议的类使用,而这种方式提供了一个很方便的、实现delegate模式的机会。
用法如下
// 数据源方法
@protocol SLWaterFlowViewDataSource <NSObject>
@required
// 一共有多少个数据
- (NSUInteger)numberOfCellsInWaterFlowView:(SLWaterFlowView *)waterFlowView;
// 返回index位置对应的cell
- (SLWaterFlowViewCell *)waterFlowView:(SLWaterFlowView *)waterFlowView cellAtIndex:(NSUInteger)index;
@optional
// 一共有多少列
- (NSUInteger)numberOfColumnsInWaterFlowView:(SLWaterFlowView *)waterFlowView;
@end
// 代理方法
@protocol SLWaterFlowViewDelegate <UIScrollViewDelegate>
@optional
// 第index位置cell对应的高度
- (CGFloat)waterFlowView:(SLWaterFlowView *)waterFlowView heightAtIndex:(NSUInteger)index;
// 选中第index位置的cell
- (void)waterFlowView:(SLWaterFlowView *)waterFlowView didSelectAtIndex:(NSUInteger)index;
// 返回间距
- (CGFloat)waterFlowView:(SLWaterFlowView *)waterFlowView marginForType:(SLWaterFlowViewMarginType)type;
@end