您的位置:首页 > 其它

数据传递的几种方式:代理,通知,block,单例

2016-01-10 14:29 232 查看



数据回调之代理:



[b]在需要传送数据出去的类中设置代理:设置代理协议,代理属性(为id类型,weak修饰),定义一个代理方法,这这个类中判断是否执行了这个代理方法,用(

if ([self.delegate respondsToSelector:@selector(代理方法)]))来判断,

代理为self,在接受数据的类中:遵守代理协议,设置(需要传送数据出去的类)的代理为self, 实现代理方法;

具体案例(线程间的通信)如下:

[/b]
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@protocol SHDownloadOperationDelegate <NSObject>

@optional

-(void)downloadWebImageWithImage:(UIImage *)downloadImage;

@end

@interface SHDownloadOperation : NSOperation

// 下载好的图片.
@property(nonatomic ,strong)UIImage *image;

// 图片的下载地址
@property(nonatomic ,copy)NSString *urlString;

// 设置代理属性 (assign 也可以)
@property(nonatomic ,weak) id<SHDownloadOperationDelegate> delegate;

@end


操作类的.m文件

#import "SHDownloadOperation.h"

@implementation SHDownloadOperation

//
-(void)main
{
// 为了防止子线程中的对象不能及时释放,手动添加 autoreleasepool.
@autoreleasepool {

// 下载图片.
self.image = [self downloadWebImageWithUrlString:self.urlString];

// 回到主线程,执行代理
dispatch_async(dispatch_get_main_queue(), ^{

// 实现代理
if ([self.delegate respondsToSelector:@selector(downloadWebImageWithImage:)]) {

[self.delegate downloadWebImageWithImage:self.image];
}

NSLog(@"执行代理的线程%@",[NSThread currentThread]);
});
}
}

// 下载图片
- (UIImage *)downloadWebImageWithUrlString:(NSString *)urlString
{
NSLog(@"downloadWebImageWithUrlString%@",[NSThread currentThread]);

NSURL *url = [NSURL URLWithString:urlString];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *image = [UIImage imageWithData:data];

return image;
}

@end


viewController.m文件中:

#import "ViewController.h"
#import "SHDownloadOperation.h"

@interface ViewController ()<SHDownloadOperationDelegate>

@property(nonatomic ,strong) NSOperationQueue *queue;

@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

-(NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
}
return _queue;
}

- (void)viewDidLoad {
[super viewDidLoad];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"touchesBegan");

// 1. 创建自定义操作.
SHDownloadOperation *op = [[SHDownloadOperation alloc] init];

// 设置代理
op.delegate = self;

// 告诉操作下载哪一张图片.
op.urlString = @"http://e.hiphotos.baidu.com/image/pic/item/8644ebf81a4c510fe5b8daf46459252dd52aa5db.jpg";

// 2. 执行操作
[self.queue addOperation:op];

}

// 实现代理方法
-(void)downloadWebImageWithImage:(UIImage *)downloadImage
{
NSLog(@"代理方法:%@",[NSThread currentThread]);

self.imageView.image = downloadImage;
}

@end




通知方法:1,注册通知观察者 2,发送通知 3,接收通知后执行注册的方法 4,移除通知
NSOperation类



#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface SHDownloadOperation : NSOperation

// 给操作一个显示图片的地址(imageView)
@property(nonatomic ,strong)UIImageView *imageView;

// 图片的下载地址
@property(nonatomic ,copy)NSString *urlString;

@end


.m文件

#import "SHDownloadOperation.h"

@implementation SHDownloadOperation

//
-(void)main
{
// 为了防止子线程中的对象不能及时释放,手动添加 autoreleasepool.
@autoreleasepool {

// 下载图片.
UIImage *image = [self downloadWebImageWithUrlString:self.urlString];

// 图片下载完毕之后,将图片传递给控制器.
// 通知:

// 发送通知: postNotificationName: 发送通知
// NotificationName: 通知名称.通知的标记,通知观察者通过通知名称来接收通知.
// object: 通知内容.需要传递的内容.

// 回到主线程发送通知
dispatch_async(dispatch_get_main_queue(), ^{

[[NSNotificationCenter defaultCenter] postNotificationName:@"downloadWebImage" object:image];

NSLog(@"发出通知的线程:%@",[NSThread currentThread]);
});

}
}

// 下载图片
- (UIImage *)downloadWebImageWithUrlString:(NSString *)urlString
{
NSLog(@"downloadWebImageWithUrlString%@",[NSThread currentThread]);

NSURL *url = [NSURL URLWithString:urlString];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *image = [UIImage imageWithData:data];

return image;
}

@end


viewController.m

#import "ViewController.h"
#import "SHDownloadOperation.h"

@interface ViewController ()

@property(nonatomic ,strong) NSOperationQueue *queue;

@property (weak, nonatomic) IBOutlet UIImageView *imageView;//在storyboard中有连线

@end

@implementation ViewController

-(NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
}
return _queue;
}

- (void)viewDidLoad {
[super viewDidLoad];

// 1. 注册通知观察者.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setUpImageWithNotify:) name:@"downloadWebImage" object:nil];

}

-(void)dealloc
{
// 移除通知观察者.
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

// 接收到通知之后,执行的方法.
// notify: 通知. 通知是同步的.(在哪条线程发送通知,也在哪条线程接收通知.)
-(void)setUpImageWithNotify:(NSNotification *)notify
{
NSLog(@"接收通知的线程:%@",[NSThread currentThread]);
// 1.取出通知内容
UIImage *image = notify.object;

// 2.显示图片
self.imageView.image = image;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"touchesBegan");

// 1. 创建自定义操作.
SHDownloadOperation *op = [[SHDownloadOperation alloc] init];

// 告诉操作下载哪一张图片.
op.urlString = @"http://e.hiphotos.baidu.com/image/pic/item/8644ebf81a4c510fe5b8daf46459252dd52aa5db.jpg";

// 2. 执行操作
[self.queue addOperation:op];

}

@end



block回传数据的方法:


1.
定义block类型.返回值/参数类型.

2.
定义block中执行的内容.确定block中执行的代码.

3.
执行block.

上面三步只要保证顺序就OK,具体哪一个步骤在哪一个对象中定义,不必关心.


自定义operation类中:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

// 1.定义block 类型
typedef void(^downloadBlock)(UIImage *image);

@interface SHDownloadOperation : NSOperation

// 下载好的图片.
@property(nonatomic ,strong)UIImage *image;

// 图片的下载地址
@property(nonatomic ,copy)NSString *urlString;

// 定义block属性
@property(nonatomic ,copy) downloadBlock block;

@end


.m文件中

#import "SHDownloadOperation.h"

@implementation SHDownloadOperation

//
-(void)main
{
// 为了防止子线程中的对象不能及时释放,手动添加 autoreleasepool.
@autoreleasepool {

// 下载图片.
self.image = [self downloadWebImageWithUrlString:self.urlString];

// block 也是同步的.

// 回到主线程执行 block.

dispatch_async(dispatch_get_main_queue(), ^{

// 3. 执行block
if (self.block) {
NSLog(@"2.执行block中的内容.");
self.block(self.image);

}
});

}
}

// 下载图片
- (UIImage *)downloadWebImageWithUrlString:(NSString *)urlString
{
NSLog(@"downloadWebImageWithUrlString%@",[NSThread currentThread]);

NSURL *url = [NSURL URLWithString:urlString];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *image = [UIImage imageWithData:data];

return image;
}

@end


viewController类中

#import "ViewController.h"
#import "SHDownloadOperation.h"

@interface ViewController ()

@property(nonatomic ,strong) NSOperationQueue *queue;

@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

-(NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
}
return _queue;
}

- (void)viewDidLoad {
[super viewDidLoad];

// block :块代码.指向结构体的指针.javascript/js:闭包.
// 闭包: 可以从函数外部访问函数内部的变量.

// block 很灵活. 可以将 block 当做一个参数传递. ===> 将一个方法当做参数传递了.

// block 使用:

// 1. 定义block类型. 返回值/参数类型.
// 2. 定义block中执行的内容. 确定block中执行的代码.
// 3. 执行block.

// 上面三步只要保证顺序就OK,具体哪一个步骤在哪一个对象中定义,不必关心.

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"touchesBegan");

// 1. 创建自定义操作.
SHDownloadOperation *op = [[SHDownloadOperation alloc] init];

// 告诉操作下载哪一张图片.
op.urlString = @"http://e.hiphotos.baidu.com/image/pic/item/8644ebf81a4c510fe5b8daf46459252dd52aa5db.jpg";

// 操作下载完图片之后,显示图片.
// 利用 block 将下面的代码传递给自定义的下载操作.

// 2. 定义 block 中执行的内容.
// block 参数 image :就是下载好的图片.
op.block = ^(UIImage *image){

self.imageView.image = image;
NSLog(@"3.最后执行这块代码.");
};

// 2. 执行操作
[self.queue addOperation:op];

}

@end


还有直接block 和间接block的回传值

这是间接的block定义的属性




在.m中 ,




在viewController中



间接block的用法:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

// 1. 定义block类型

@class SHDownloadOperation;

typedef void(^downloadBlock)(SHDownloadOperation *op);

@interface SHDownloadOperation : NSOperation

// 下载好的图片.
@property(nonatomic ,strong)UIImage *image;

// 图片的下载地址
@property(nonatomic ,copy)NSString *urlString;

// 定义block属性,来接收blk中传递过来的函数.
@property(nonatomic ,copy)downloadBlock block;

// 定义一个方法.用来传递 block 的方法.(接口,方便外接书写block.)
// 参数: block 类型的参数. blk:形参
-(void)downloadImageWithDownloadBlock:(downloadBlock)blk;

@end


#import "SHDownloadOperation.h"

@implementation SHDownloadOperation

//

-(void)main

{

//
为了防止子线程中的对象不能及时释放,手动添加 autoreleasepool.

@autoreleasepool {

// 下载图片.

self.image = [selfdownloadWebImageWithUrlString:self.urlString];

//
回到主线程显示图片

dispatch_async(dispatch_get_main_queue(), ^{

// 3.执行 block.

if (self.block) {

NSLog(@"准备执行最后的block.");

self.block(self);

}

});

}

}

// 将block当做一个参数传递.

// 2. 确定 self.block中执行的内容.

-(void)downloadImageWithDownloadBlock:(downloadBlock)blk

{

if (blk) {

NSLog(@"2.确定 self.block中执行的内容.");

self.block = blk;

}

}

// 下载图片

- (UIImage *)downloadWebImageWithUrlString:(NSString *)urlString

{

NSLog(@"downloadWebImageWithUrlString%@",[NSThreadcurrentThread]);

NSURL *url = [NSURLURLWithString:urlString];

NSData *data = [NSDatadataWithContentsOfURL:url];

UIImage *image = [UIImageimageWithData:data];

return image;

}

@end

控制器中

#import "ViewController.h"
#import "SHDownloadOperation.h"

@interface ViewController ()

@property(nonatomic ,strong) NSOperationQueue *queue;

@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

-(NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
}
return _queue;
}

- (void)viewDidLoad {
[super viewDidLoad];

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"touchesBegan");

// 1. 创建自定义操作.
SHDownloadOperation *op = [[SHDownloadOperation alloc] init];

// 告诉操作下载哪一张图片.
op.urlString = @"http://e.hiphotos.baidu.com/image/pic/item/8644ebf81a4c510fe5b8daf46459252dd52aa5db.jpg";

// 告诉操作图片下载完毕之后做什么!
// 图片下载完毕之后,执行下面block中的内容.
[op downloadImageWithDownloadBlock:^(SHDownloadOperation *op) {

NSLog(@"3.图片下载完毕之后,最后执行这块代码!");
// 显示图片.
self.imageView.image = op.image;
}];

// 2. 执行操作
[self.queue addOperation:op];

}

@end


单例:这段代码请定义一个Header.file文件放进去 作用:定义一个类方法来创建单例对象;
// .h
#define single_interface(class)  + (class *)shared##class;

// .m
// \ 代表下一行也属于宏
// ## 是分隔符
#define single_implementation(class) \
static class *_instance; \
\
+ (class *)shared##class \
{ \
if (_instance == nil) { \
_instance = [[self alloc] init]; \
} \
return _instance; \
} \
\
+ (id)allocWithZone:(NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
}
单例类的.h文件
#import <Foundation/Foundation.h>
#import "Singleton.h"

@interface UserInfo : NSObject

single_interface(UserInfo)

@property (nonatomic,copy)NSString* title;

@end


单例类的.m文件

#import "UserInfo.h"

@implementation UserInfo
single_implementation(UserInfo)

@end


需要传值出去的控制器的.m文件
#import "TwoViewController.h"
#import "UserInfo.h"

@interface TwoViewController ()

@end

@implementation TwoViewController
//点击按钮发送信息
- (IBAction)btnClick:(UIButton *)sender {

//TODO:单例实现
UserInfo *info = [UserInfo sharedUserInfo];
info.title = self.textField.text;

[self dismissViewControllerAnimated:YES completion:^{

}];


接收值传递过来的控制器的.m文件中

#import "ViewController.h"
#import "TwoViewController.h"
#import "UserInfo.h"

@interface ViewController ()//<TwoViewControllerDelegate>
@property (weak, nonatomic) IBOutlet UILabel *myLabel;

@end

@implementation ViewController
//视图即将出现时 利用单例传值
-(void)viewWillAppear:(BOOL)animated{

[super viewWillAppear:animated];

//TODO:单例实现
UserInfo *info = [UserInfo sharedUserInfo];
self.myLabel.text = info.title;
}

- (void)viewDidLoad {
[super viewDidLoad];

}
- (IBAction)btnClick:(UIButton *)sender {

TwoViewController *twoVC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"TwoViewController"];

[self presentViewController:twoVC animated:YES completion:nil];

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: