数据传递的几种方式:代理,通知,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]; }
相关文章推荐
- UIScroollView的使用和注意点
- 单片机第11课:串口通信查询方式---从计算机接受数据
- MySQL的root用户密码忘了怎么办
- 面试小记
- jQuery实现的调整表格行tr上下顺序
- 含有日期类型对象的序列化合反序列化
- 软件工程总结博客
- CCNP学习笔记21--GLBP(思科私有)
- 机器学习之决策树
- LeetCode-46-Permutations(DFS)-Medium
- 《梦断代码》摘录及感悟
- 【CSS3】CSS3 滤镜实现
- 通过js写的一个比较简单的点击切换图片效果
- 工作中一点心理技巧、提升效率
- Java后台开发(2)——JVM参数设置和分析
- web前端开发笔记
- 知乎接口
- 158_弹性碰撞 Physics Experiment (POJ No 3684)
- 【架构】架构没你想的那么难之三层架构
- java28.XML操作------DOM方式解析XML数据