数据回调之代理:
在需要传送数据出去的类中设置代理:设置代理协议,代理属性(为id类型,weak修饰),定义一个代理方法,这这个类中判断是否执行了这个代理方法,用(
if ([self.delegate respondsToSelector:@selector(代理方法)]))来判断,
代理为self,在接受数据的类中:遵守代理协议,设置(
需要传送数据出去的类
)的代理为self, 实现代理方法;
具体案例(线程间的通信)如下:
#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 <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
#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 "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
#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
#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类
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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface SHDownloadOperation : NSOperation
// 给操作一个显示图片的地址(imageView)
@property(nonatomic ,strong)UIImageView *imageView;
// 图片的下载地址
@property(nonatomic ,copy)NSString *urlString;
@end
#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 "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
#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
#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 <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
#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 "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
#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的回传值
#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定义的属性
在.m中 ,
在viewController中
#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
// .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
#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];
}