Block与协议


延展:Extension

  1. 是一个特殊的分类,所以延展也是类的一部分
  2. 特殊之处:
  • 没有名字
  • 只有声明没有实现,和本类共享一个实现
  1. 延展的语法
  • 语法
@interface 本类名 ()
@end
	//没有实现,和本类共享一个实现
  1. 延展和分类的区别
  • 分类有名字,延展没哟名字,是一个匿名的分类
  • 每一个分类都有单独的声明和实现,而延展只有声明,没有单独的实现,和本类共享一个实现
  • 分类中只能新增方法,而延展中任意的成员都可以写
  • 分类中可以写@property,但是只会生成getter,setter的声明。延展中写@property会自动生成私有属性,也会生成getter,setter的声明和实现。
  1. 延展的应用场景
  • 要为类写一个私有的@property,生成getter和setter方法只能在类的内部访问,不能在外部访问。
  • 延展100%的情况下不会独占1个文件,都是将延展直接写在本类的实现文件中
@interface User ()
@end

@implementation User

@end
  • 为类写一个私有方法,也建议把声明写在延展里。
  • 延展天生就是来私有化类的成员的。

####block

  1. block是一个数据类型
  • block是一个数据类型,所以我们可以声明一个block类型的变量
  • block类型的变量专门存储一段代码,这段代码可以有参数,可以有返回值
  1. block变量的声明
  • 在声明block变量的时候,必须指定这个block变量存储的代码是否哟参数,是否有返回值,一旦指定以后,这个block变量中就只能存储这样的代码了。
  • 声明语法:
返回值类型(^block变量的名称)(参数类型);
 void (^myblock1)();//表示声明了一个block类型的变量,没返回值也无参数
  • 初始化block变量
^返回值类型(参数类型){
	代码段;
myblock1 = ^void(){
	NSlog(@"一个无参无返回值的block变量")
}
}
  1. 执行
//无参无返回值
block变量名();
//有返回值(接收数据)
返回值类型  名称 = block变量名()
//有参数
返回值类型  名称 = block变量名(a,b )

  1. 简写
  • 如果没有返回值,代码中的void可以省略(声明变量的不可以省略)
void(^myblock1)()=^(){
	。。。
}
  • 无参数小括号可省略
void(^myblock1)()=^{
	。。。
}
  • 声明block变量的时候,如果有指定参数,可以只写参数的类型而不写参数的名称
int(^myblock1)(int,int)=^int(int num1 ,int num2){
	int num3 = num1+num2;
	return num3
}
  • 无论代码段是否有返回值,在写代码的时候,可以不写返回值类型,省略。(系统自动确定)
int(^myblock1)(int,int)=^(int num1 ,int num2){
	int num3 = num1+num2;
	return num3
}
  • 建议:不简写(提高可读性)

  • typedef简写(将长类型定义为短类型)

typedef void (^NewType)();
//引用
NewType block1;
NewType block2;
  1. 关于block块访问外部变量的问题
  • 在block代码块的内部可以取定义在外部变量的值,定义在外部的局部变量和全局变量
  • 在block代码块的内部可以修改全局变量的值,但是不能修改定义在外部的局部变量的值,
  • 如果你希望我们定义的局部变量可以允许在block代码的内部去修改,那么就为这个局部变量加一个__block的修饰符。
  1. block作为函数的参数
void text(void (^block1)())
	{
	block();
}

int main(int argc, const char * argv[]) {
	NewType type =^{
		NSLog(@"哈哈");
	};
	test(type);
	//另一种方式直接传值
	text(^{
		NSLog(@"哈哈");
	});
}


  1. 作用:
  • 可以将调用者自己写的一段代码,传递到函数的内部去执行。
  1. 什么时候使用
  • 当方法的内部需要执行一个功能,但是这个功能的具体的实现,函数的内部不确定,那么这个时候,就使用block让调用者将这功能的具体实现传递过去。
  1. block也可以作为函数的返回值
  • 当将block作为函数的返回值的时候,返回值的类型就必须使用typedef定义的短类型。
  1. block与函数 相同点: 都是封装一段代码 不同点:
  • block是一个数据类型,函数只是一个函数
  • 我们可以声明block类型的变量,函数只是函数
  • block可以作为函数的参数,而函数不能直接作为函数的参数

协议

  1. 专门用来声明一大堆方法。(不能声明属性,也不能实现方法,只能用来写方法的声明)。只要某个类遵守了这个协议,就相当于拥有了这个协议中的所有的方法声明。
  2. 协议的声明
@protocol 协议名称 <NSObject>
方法的声明;
@end
  1. 类遵守协议
#import "协议.h"

@interface User : NSObject <协议1,协议2>
  • 当一个类遵守了1份协议,这个类就拥有这个协议中的所有的方法声明,仅仅是只有声明而已,还要自己实现,如果不实现呢?也不会报错,只有一个警告而已。
  1. @required 与@optional
  • 使用@required (默认):不实现方法,编译器会给警告
  • 使用@optional:不实现方法,编译器不会给警告
  • 都可以运行
  1. 继承
  • 协议之间也可以继承
@protocol 协议名称 <父协议名>
方法的声明;
@end
  1. 指针遵守指定协议的任意对象(否则报警告)
NSObject<协议名称> *指针名
//或
id<协议名称> *指针名
学习