block的四种基本使用方式

简介: block的四种基本使用方式

1.单例声明的block

2.被包含的对象声明的block

3.调用者的block被当变量传入被调用对象

4.block参数

block使用要注意使用不当,容易出现内存泄漏而崩溃,要注意判空处理,使用时尽量使用弱引用( __weak typeof(self) weakSelf = self;)。

第一种方式:单例声明的block。

它可以全局使用,当多个地方使用该block时,只有最后一个注册的单例block有用。所以你想在多个类中使用相同的处理,那么你就要在单例中声明多个不同的block.

SingleObject.h文件:

#import <UIKit/UIKit.h>

#import <Foundation/Foundation.h>

typedef void(^TimerProgress1)();

@interface SingleObject : NSObject


(SingleObject *)sharedInstance;

(void)regisiterTimerProgress1Callback:(TimerProgress1)callback;

@end

SingleObject.m文件

#import “SingleObject.h”

@implementation SingleObject

+(SingleObject *) sharedInstance

{

static SingleObject *sharedInstace = nil;

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

sharedInstace = [[self alloc] init];

});

return sharedInstace;

}

-(void)progress1

{

if (self.timerProgress1) {

self.timerProgress1();

}

}

(void)regisiterTimerProgress1Callback:(TimerProgress1)callback

{

self.timerProgress1 = callback;

}

@end

单例子block的使用:

(void)regisiterSingleObjectTimerProgress1Callback {

__weak typeof(self) weakSelf = self;

[[SingleObject sharedInstance] regisiterTimerProgress1Callback:^{

[weakSelf progress1];

}];

}

注意:单例block在页面销毁时要把它,置空,不然就是原来所在页面销毁了,由于它是全局的终生的,它还活着,你判空时发现它不是空,还会继续回调。就是你的内存泄漏了,只是泄漏的很少,不容易观察到。需要在dealloc函数里销毁它。

单例block可以代替一对一的通知。并且不存在通知的注册时间,是实时注册,实时生效。通知是在注册后不是立即生效,需要时间调度到才能生效,这个时间极短。部分多线程应用,当在通知还在注册过程中发送了通知,有几率闪退,而单例block不存在这样的问题。

- (void)dealloc
{
    NSLog(@"dealloc");
    [AESingleObject sharedInstance].newForgetPasswordViewControllerTimerCallBack = nil;
}

一个类的对象中的函数可以访问全局的单例。

使用系统的单例的block:

__weak typeof(self) weakSelf = self;

AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;

[app regisiterXYContinueListenOrderCallback:^{

[weakSelf continueListenOrder];

}];

第二种方式:对象声明的block.

控制器页面包含的控件或使用的对象的block的使用,控制器间的block使用.

第1种,控制器页面包含的控件block的使用。

CustomNavigationBar.h文件

#import <UIKit/UIKit.h>

typedef void (^backBlock)(BOOL iSuccess);

@interface CustomNavigationBar : UIView


(void)backResult:(backBlock)back;

@end

CustomNavigationBar.m文件

#import “CustomNavigationBar.h”

@interface CustomNavigationBar ()

@property (nonatomic,copy) backBlock backResult;

@end

@implementation CustomNavigationBar


(instancetype)initWithFrame:(CGRect)frame{


if (self=[super initWithFrame:frame ]) {

  [self addchildV];

}


return self;


}


(void)backResult:(backBlock)back{


self.backResult = back;

}


(void)backAction:(UIButton *)sender {

if(self.backResult)

{

self.backResult(YES);

}

}

@end

页面包含的控件的block使用如下:

-(void)loadButtonAction

{

[_customCommonNavigationBar backResult:^(BOOL iSuccess) {

[self.navigationController popViewControllerAnimated:YES];

}];

}

第2种情况,页面控制器间的block使用。

LoginViewController.h文件

#import <UIKit/UIKit.h>

#import “YXBaseViewController.h”

@interface LoginViewController : YXBaseViewController

{

}

//登陆成功以后的回调

@property (nonatomic, copy) void (^didClickLoginSuccessBlock)();

@end

LoginViewController.m文件

#import “LoginViewController.h”

@interface LoginViewController ()

{

}

@end

@implementation LoginViewController


(void)loginAction:(UIButton *)sender {

[self.view endEditing:YES];

if (self.didClickLoginSuccessBlock) {

self.didClickLoginSuccessBlock();

}

}

@end

其它页面使用block.

-(void)commitRootViewController:(NSDictionary *)launchOptions

{

LoginViewController *LoginVC = [[LoginViewController alloc] init];

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:LoginVC];

self.window.rootViewController = nav;

[self.window makeKeyAndVisible];

[LoginVC setDidClickLoginSuccessBlock:^{

  [RootNav pushViewController:[self commitYXView] animated:NO];

}];

}

第3种情况:调用者的block被当变量传入被调用对象。

前面两种情况都是说明的A对象的成员变量或函数内的变量是声明block的B对象,那么是否可以A页面调用了B页面,进入B页面,B页面是否可以直接控制A页面的部分控件的显示内容。注意,B页面看似无法持有A页面的对象指针,不然就破坏了object c的封装性(你像C++一样把A页面的self当对象指针传递给B页面,编译器会告警,虽然你可能实现你的功能,那样使用是不合法的。),你可以在跳转B页面前,申请个block,把这个bock传递给B页面,那么你就可以在B页面控制A页面的部分控件了。这种方法本质方法还是指针的传递,和C++的二级指针相似。

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    [userInfo setSafeObject:[GBAMapOrientation defaultOrientation].locationEntity.citycode forKey:@"cityCode"];
    void(^block)(GBSelectAirportEntity *entity) = ^(GBSelectAirportEntity *entity){
        @strongify(self);
        self.flightArrAirportFullName = entity.flightArrAirport;
    };
    [userInfo setSafeObject:block forKey:@"block"];
    [MGJRouter openURL:@"gb://selectAirport" withUserInfo:userInfo completion:nil];

这样通过三种block三种方法就能实现,从A页面包含或跳转到B页面,A页面可以控制B页面,B页面也能控制A页面,达到互相控制的目的。

第4种情况:block参数

咱们发送网络请求等封装的接口就是这种类型。咱们看一下它的简单模型:

ODCTripManageEntity.h

#import <Foundation/Foundation.h>
@class ODCTripListEntity;
@interface ODCTripManageEntity : NSObject
- (void)deCodeFilesWithblock:(void(^)())block;
@end

ODCTripManageEntity.m

@implementation ODCTripManageEntity
#pragma mark - 加载本地行程文件
- (void)deCodeFilesWithblock:(void(^)())block;
{
    if (block) {
        block();
    }   
}
@end

调用者:

    @weakify(self);
    [self.tabview.refreshView startAnimating];
    [self.tripManageEntity deCodeFilesWithblock:^{
        @strongify(self);
         [self.tabview.refreshView endAnimating];
        [self.tabview reloadData];
    }];
目录
相关文章
|
4月前
|
前端开发 JavaScript
html中id和class的相同和不同之处及用法的规范与区别
在HTML中,`id`和`class`都用于标识和选择元素,但存在一些关键差异。
|
JavaScript
热点面试题:JS 中 call, apply, bind 概念、用法、区别及实现?
热点面试题:JS 中 call, apply, bind 概念、用法、区别及实现?
UniAPP template 与 block 的使用区别
UniAPP template 与 block 的使用区别
702 0
|
缓存
ALSTOM V4550220-EN 复制CPU中的少量组件来支持MT
ALSTOM V4550220-EN 复制CPU中的少量组件来支持MT
104 0
ALSTOM V4550220-EN 复制CPU中的少量组件来支持MT
|
Go 开发者
switch 基本使用|学习笔记
快速学习 switch 基本使用
switch 基本使用|学习笔记
|
JavaScript 前端开发
Web前端学习:jQuery基础--1【简介和安装、语法使用、三种选选择器的使用(元素、class、id)】(附操作源码)
Web前端学习:jQuery基础--1【简介和安装、语法使用、三种选选择器的使用(元素、class、id)】(附操作源码)
292 0
Web前端学习:jQuery基础--1【简介和安装、语法使用、三种选选择器的使用(元素、class、id)】(附操作源码)
|
编译器 C++
block原理
block本质上也是一个OC对象,它内部也有个isa指针;block是封装了函数调用以及函数调用环境的OC对象
225 0
block原理
html+css实战32-input基本使用
html+css实战32-input基本使用
124 0
html+css实战32-input基本使用
|
API iOS开发 Perl
【封装富文本API,采用block实现链式编程】(block 的妙用:结合block和方法的优点实现iOS的链式编程)
【封装富文本API,采用block实现链式编程】(block 的妙用:结合block和方法的优点实现iOS的链式编程)
120 0
【封装富文本API,采用block实现链式编程】(block 的妙用:结合block和方法的优点实现iOS的链式编程)

热门文章

最新文章