1.块的基础知识
块与函数类似,只不过是直接定义在另外一个函数里的,和定义它的那个函数共享同一个范围内的东西。块用^符号来表示,后面跟着一堆花括号,括号里面是是块的实现代码。
举例下面就是个简单的块代码
^{
block implementation here
}
块其实就是一个值,而且自有其数据类型。与int float 或Object-c对象一样,也可以把块赋给变量,然后像使用其他变量那样使用它。块类型的语法
块的常见用法
1.块代码作为方法参数与函数指针类似。下面列出一个带返回值和返回类型的块
int (^AddBlock)(int a, int b) =^(int a, int b) {
return a + b;
}
块的强大之处在于:在声明它的范围里,所有变量都可以为其所捕获。这也就是说,那个范围里的所有变量,在块里依然可以使用。
int additional = 5;
int (^AddBlock)(int a, int b) =^(int a, int b) {
return a + b + additional;
}
int add = AddBlock(2,5) = 12;
默认情况下 块所捕获的变量是不可以在块内修改的。如果想修改外部变量,那么变量定义的时候需要加上__block 去修饰变量
__block int additional = 5;
int (^AddBlock)(int a, int b) =^(int a, int b) {
additional = additional +2;
return a + b + additional;
}
如果块所捕获的变量是对象类型,那么就会自动保留它,系统在释放块的时候,也会将其一并释放。
如果将块定义在Object-c类的实例变量,那么除了可以访问类的所有实例变量之外,还可以使用self变量。块总能捕获实例变量所以在声明时无需加__block。不过通过读取或写入操作捕获了实例变量,那么也会自动把self变量一并捕获了,因为实例变量是与self所指代的实例关联在一起的。例如,下面这个块声明在EOCClass类的方法中
@interface EOCClass
- (void)anInstanceMethod{
void (^someBlock)()= ^{
_anInstanceVariable = @"some";
NSlog(@"%@", _anInstanceVariable);
}
}
如果某个EOCClass实例正在执行anInstanceMethod方法,那么self变量就指向此实例。由于块里没有明确使用self变量,所以很容易就会忘记self变量其实也为块所捕获了。直接访问实例变量和通过self来访问是等效的:
self->_anInstanceVAriable=@"some";之所以要捕获self变量原因在于此。我们经常通过属性访问实例变量,这种情况下,就要指明self了:
self.aProperty = @"Something";
然而一定要记住self也是个对象,因而在捕获它时也会将其保留。如果self所指代的那个对象同时也保留了块,这种情况通常会导致保留环。
2.block作为方法参数的常见用法
//声明
typedef void(^ClickBlock)(NSInteger index);
//block属性
@property (nonatomic, copy) ClickBlock imageClickBlock;
例子2:作方法参数
//声明
typedef void (^handleBlock)();
//block作参数
- (void)requestForRefuseOrAccept:(MessageBtnType)msgBtnType messageModel:(MessageModel *)msgModel handle:(handleBlock)handle{
...
2.3.3 在定义方法时,声明Block型的形参
- (void)yourMethod:(return_type (^)(var_type))blockName;
- (void)addClickedBlock:(void(^)(id obj))clickedAction;
- (void)addClickedBlock:(void(^)(id obj))clickedAction{
self.clickedAction = clickedAction;
// :先判断当前是否有交互事件,如果没有的话。。。所有gesture的交互事件都会被添加进gestureRecognizers中
if (![self gestureRecognizers]) {
self.userInteractionEnabled = YES;
// :添加单击事件
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
[self addGestureRecognizer:tap];
}
}
- (void)tap{
if (self.clickedAction) {
self.clickedAction(self);
}
}
#import <Foundation/Foundation.h>
typedef void (^SureActionBlock)(void);
typedef void (^CancleActionBlock)(void);
@interface FDDAlertViewController : NSObject
@property (nonatomic, copy) SureActionBlock sureActionBlock;
@property (nonatomic, copy) CancleActionBlock cancleActionBlock;
+ (instancetype)defaultAlertViewController;
- (void)showAlertViewWithTitle:(NSString *)title
message:(NSString *)message
sureActionBlock:(SureActionBlock)sureBlock
cancleActionBlock:(CancleActionBlock)cancleBlock;
@end
@implementation FDDAlertViewController
+ (instancetype)defaultAlertViewController
{
static id instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (void)showAlertViewWithTitle:(NSString *)title
message:(NSString *)message
sureActionBlock:(SureActionBlock)sureBlock
cancleActionBlock:(CancleActionBlock)cancleBlock{
self.sureActionBlock =sureBlock;
self.cancleActionBlock =cancleBlock;
NSString *OKStr = AppLocalString(@"OK");
NSString *cancleStr = AppLocalString(@"cancle");
UIAlertController *Alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:OKStr style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (self.sureActionBlock) {
self.sureActionBlock();
}
}];
UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:cancleStr style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
if (self.cancleActionBlock) {
self.cancleActionBlock();
}
}];
[Alert addAction:cancleAction];
[Alert addAction:sureAction];
//获取当前展示的controller
[[self currentViewController] presentViewController:Alert animated:YES completion:nil];
}
- (UIViewController *)currentViewController {
UIWindow *window = [[UIApplication sharedApplication].delegate window];
UIViewController *presentedVC = [[window rootViewController] presentedViewController];
if (presentedVC) {
return presentedVC;
} else {
return window.rootViewController;
}
}
@end
网友评论