通知(Notification) 、 应用间通信(一)
1 使用通知中心发送消息
1.1 问题
当一个对象需要向多个接受者发送消息的,或者不用知道消息的接收者是谁,就可以使用IOS提供的NSNotificationCenter通知中心,本案例使NSNotificationCenter通知中心改变界面上所有按钮的颜色,如图-1所示:
图-1
1.2 方案
首先在创建好的Xcode项目的Storyboard中拖放两个场景,其中第一个场景带有NavigationController,这两个场景分别和ViewController类以及ChangeColorViewController进行绑定,这两个类全都继承至UIViewController。
在第一个场景中拖放一个Button控件,标题设置为ChangeColor,选中Button控件按住Control键往第二个场景拖拽,实现第一个场景跳转到第二个场景,跳转模式选择Push。
在第二个场景上拖放三个Button控件,标题分别设置为Blue、Red和Yellow,代表各自的颜色,并将这三个按钮关联成ChangeColorViewController的同一个方法chooseColor:。
其次实现ChangeColorViewController类中的chooseColor:方法,该方法的功能就是根据用户选择的颜色,使用postNotificationName:object:userInfo:方法进行发通知,该方法中需要将用户选择的颜色通过userInfo传递给通知的接受者。
然后创建一个TRButton类继承至UIButton,重写init初始化方法,按钮是通知的接受者,需要在init方法中使用addObserver:selector:name:object:进行注册通知,name参数是通知名字,这里命名为ChangeColor,selector参数是当接受到通知时调用的方法,这里定义一个方法changeColor:,该方法的功能就是改变按钮的颜色,该方法的参数是NSNotification类型的对象,记录着通知发送者传递过来的信息。
实现changeColor方法,该方法中通过NSNotification类型的参数obj的useInfo属性获取到用户选择的颜色,根据用户选择的颜色修改按钮的背景色。
最后在ViewController类中的viewDidLoad方法中用代码创建三个TRButton类型的按钮,运行程序即可根据用户的选择统一修改三个按钮的背景颜色。
1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:搭建Storyboard界面
首先在创建好的Xcode项目的Storyboard中拖放两个场景,其中第一个场景带有NavigationController,这两个场景分别和ViewController类以及ChangeColorViewController进行绑定,这两个类全都继承至UIViewController。
在第一个场景中拖放一个Button控件,标题设置为ChangeColor,选中Button控件按住Control键往第二个场景拖拽,实现第一个场景跳转到第二个场景,跳转模式选择Push。
在第二个场景上拖放三个Button控件,标题分别设置为Blue、Red和Yellow,代表各自的颜色,并将这三个按钮关联成ChangeColorViewController的同一个方法chooseColor:,Storyboard中的界面如图-2所示:
图-2
步骤二:实现chooseColor:方法
实现ChangeColorViewController类中的chooseColor:方法,该方法的功能就是根据用户选择的颜色,使用postNotificationName:object:userInfo:方法进行发送通知,name参数是通知的名字,userInfo是一个NSDictionary类型的参数,记录着需要传递给通知接受者的信息。
chooseColor:方法中需要将用户选择的颜色通过userInfo传递给通知的接受者,代码如下所示:
- - (IBAction)chooseColor:(UIButton *)sender {
- NSString *title = sender.titleLabel.text;
- [[NSNotificationCenter defaultCenter] postNotificationName:@"ChangeColor" object:nil userInfo:@{@"color":title}];
- }
步骤三:创建TRButton类
首先创建一个TRButton类继承至UIButton,然后重写init初始化方法,按钮是通知的接受者,需要在init方法中使用addObserver:selector:name:object:进行注册通知,name参数是通知的名字,需要和发送的通知名字保持一致,所以这里命名为ChangeColor,selector参数是当接受到通知时调用的方法,这里定义一个方法changeColor:,代码如下所示:
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
- [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(changeColor:) name:@"ChangeColor" object:nil];
- }
- return self;
- }
changeColor:方法的功能就是改变按钮的颜色,该方法的参数是一个NSNotification类型的对象,记录着通知发送者传递过来的信息。可以根据NSNotification类型的参数的useInfo属性获取到用户选择的颜色,根据用户选择的颜色修改按钮的背景色,代码如下所示:
- -(void)changeColor:(NSNotification*)obj{
- NSString *title = [obj.userInfo valueForKey:@"color"];
- if([title isEqualToString:@"Blue"])
- {
- [self setBackgroundColor:[UIColor blueColor]];
- }else if([title isEqualToString:@"Red"]){
- [self setBackgroundColor:[UIColor redColor]];
- }else {
- [self setBackgroundColor:[UIColor yellowColor]];
- }
- }
步骤四:创建TRButton按钮
在ViewController类中的viewDidLoad方法中用代码创建三个TRButton类型的按钮,并设置相关属性,代码如下所示:
- - (void)viewDidLoad {
- [super viewDidLoad];
- TRButton *btn1 = [[TRButton alloc]init];
- [btn1 setFrame:CGRectMake(100, 100, 100, 50)];
- [btn1 setTitle:@"btn1" forState:UIControlStateNormal];
- [self.view addSubview:btn1];
- TRButton *btn2= [[TRButton alloc]init];
- [btn2 setFrame:CGRectMake(100, 170, 100, 50)];
- [btn2 setTitle:@"btn2" forState:UIControlStateNormal];
- [self.view addSubview:btn2];
- TRButton *btn3 = [[TRButton alloc]init];
- [btn3 setFrame:CGRectMake(100, 240, 100, 50)];
- [btn3 setTitle:@"btn3" forState:UIControlStateNormal];
- [self.view addSubview:btn3];
- }
运行程序即可根据用户的选择统一修改三个按钮的背景颜色。
1.4 完整代码
本案例中,ViewController.m文件中的完整代码如下所示:
- #import "ViewController.h"
- #import "TRButton.h"
- @implementation ViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- TRButton *btn1 = [[TRButton alloc]init];
- [btn1 setFrame:CGRectMake(100, 100, 100, 50)];
- [btn1 setTitle:@"btn1" forState:UIControlStateNormal];
- [self.view addSubview:btn1];
- TRButton *btn2= [[TRButton alloc]init];
- [btn2 setFrame:CGRectMake(100, 170, 100, 50)];
- [btn2 setTitle:@"btn2" forState:UIControlStateNormal];
- [self.view addSubview:btn2];
- TRButton *btn3 = [[TRButton alloc]init];
- [btn3 setFrame:CGRectMake(100, 240, 100, 50)];
- [btn3 setTitle:@"btn3" forState:UIControlStateNormal];
- [self.view addSubview:btn3];
- }
- @end
本案例中,ChangeColorViewController.m文件中的完整代码如下所示:
- #import "ChangeColorViewController.h"
- @implementation ChangeColorViewController
- - (IBAction)chooseColor:(UIButton *)sender {
- NSString *title = sender.titleLabel.text;
- [[NSNotificationCenter defaultCenter] postNotificationName:@"ChangeColor" object:nil userInfo:@{@"color":title}];
- }
- @end
本案例中,ChangeColorViewController.m文件中的完整代码如下所示:
- #import "TRButton.h"
- @implementation TRButton
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
- [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(changeColor:) name:@"ChangeColor" object:nil];
- }
- return self;
- }
- -(void)changeColor:(NSNotification*)obj{
- NSString *title = [obj.userInfo valueForKey:@"color"];
- if([title isEqualToString:@"Blue"])
- {
- [self setBackgroundColor:[UIColor blueColor]];
- }else if([title isEqualToString:@"Red"]){
- [self setBackgroundColor:[UIColor redColor]];
- }else {
- [self setBackgroundColor:[UIColor yellowColor]];
- }
- }
- @end
2 通过UIActivityViewController实现应用间的通信
2.1 问题
UIActivity是IOS6提供的一个十分有用的控件,可以十分方便的将文字、图片等内容进行分享,比如分享到微信、新浪微博、发邮件、发短信给等,也可以通过自定义按钮实现定制功能,本案例通过UIActivityViewController和自定义Activity实现应用间的通信,如图-3所示:
图-3
2.2 方案
首先在创建好的Xcode项目的Storyboard中拖放一个TextField控件和两个Button控件,将两个Button的标题设置为“分享”和“自定义”,将textField控件关联成ViewController的属性textField,两个Button关联成ViewController的方法share和customActivity。
其次在share方法中创建UIActivityViewController对象,使用初始化方法initWithActivityItems:applicationActivities:进行初始化,activityItems是一个NSArray类型的参数,代表执行activity中用到的数据对象数组,applicationActivities参数是一个UIActivity对象的数组,代表了应用程序支持的自定义服务,这个参数可以是nil。
这里share方法中直接使用系统提供的服务即可,可以通过设置excludedActivityTypes属性去掉不需要包含的服务,然后通过present方法显示出来。
然后实现customActivity方法,该方法中提供自定义服务,所以首先需要自定义一个服务,即创建一个TRStringReverseActivity继承至UIActivity,提供自定义服务将需要处理的字符串数据进行反转。在TRStringReverseActivity类中重写父类的方法实现弹出对话框,显示反转字符串的需求。
最后实现customActivity方法,该方法中创建UIActivityViewController对象,然后创建一组NSArray类型的字符串对象itemsToShare和TRStringReverseActivity对象stringReverseActivity,分别作为activityItems参数和applicationActivities参数,然后通过present方法显示出来。
2.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:搭建Storyboard界面
首先在创建好的Xcode项目的Storyboard中拖放一个TextField控件和两个Button控件,将两个Button的标题设置为“分享”和“自定义”,将textField控件关联成ViewController的属性textField,两个Button关联成ViewController的方法share和customActivity,Storyboard中的界面如图-4所示:
图-4
步骤二:实现share方法
首先在share方法中创建UIActivityViewController对象,使用初始化方法initWithActivityItems:applicationActivities:进行初始化,activityItems是一个NSArray类型的参数,代表执行activity中用到的数据对象数组,applicationActivities参数是一个UIActivity对象的数组,代表了应用程序支持的自定义服务,这个参数可以是nil,代码如下所示:
- - (IBAction)shared
- {
- UIActivityViewController * activityVC = [[UIActivityViewController alloc]initWithActivityItems:@[self.textField.text] applicationActivities:nil];
- }
然后设置excludedActivityTypes属性去掉不需要包含的服务,通过present方法显示出来,代码如下所示:
- - (IBAction)shared
- {
- UIActivityViewController * activityVC = [[UIActivityViewController alloc]initWithActivityItems:@[self.textField.text] applicationActivities:nil];
- //设置不包含的activity
- activityVC.excludedActivityTypes = @[UIActivityTypeCopyToPasteboard];
- [self presentViewController:activityVC animated:YES completion:nil];
- }
运行程序点击分享按钮,从应用底部出现分享框,如图-5所示:
图-5
点击Mail服务按钮,程序自动跳转到Mall应用,如图-6所示:
图-6
步骤三:创建自定义服务类
首先创建一个TRStringReverseActivity继承至UIActivity,提供自定义服务将需要处理的字符串数据进行反转。
其次在TRStringReverseActivity类中重写父类的方法activityType、activityTitle和activityImage设置服务的类型、标题和图片,代码如下所示:
- //服务的类型
- - (NSString *)activityType
- {
- return [[NSBundle mainBundle].bundleIdentifier stringByAppendingFormat:@".%@", NSStringFromClass([self class])];
- }
- //显示在分享框中的服务的名称
- - (NSString *)activityTitle
- {
- return @"返转";
- }
- //显示在分享框的服务的图片
- - (UIImage *)activityImage
- {
- return [UIImage imageNamed:@"random"];
- }
然后通过重写父类的方法canPerformWithActivityItems:、prepareWithActivityItems:和performActivity设置服务按钮的显示、解析数据和实现相应的自定义服务功能,代码如下所示:
- //是否显示服务按钮
- - (BOOL)canPerformWithActivityItems:(NSArray *)activityItems
- {
- for (id object in activityItems) {
- if ([object isKindOfClass:[NSString class]]) {
- return YES;
- }
- }
- return NO;
- }
- //解析服务数据时调用
- - (void)prepareWithActivityItems:(NSArray *)activityItems
- {
- NSMutableArray *stringObjects = [[NSMutableArray alloc]init];
- for (id object in activityItems) {
- if ([object isKindOfClass:[NSString class]]) {
- [stringObjects addObject:object];
- }
- }
- self.activityItems = stringObjects;
- }
- //执行服务,根据自己的应用做相应的处理
- - (void)performActivity
- {
- NSMutableString *reverseStrings = [[NSMutableString alloc]init];
- //反转字符串
- for (NSString *string in self.activityItems) {
- [reverseStrings appendString:[self reverseString:string]];
- [reverseStrings appendString:@"\n"];
- }
- UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"字符串返转" message:reverseStrings delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil];
- [alert show];
- }
最后实现一个字符串反转的方法reverseString:,代码如下所示:
- - (NSString *)reverseString:(NSString *)paramString
- {
- NSMutableString *reversed = [[NSMutableString alloc]init];
- for (NSInteger counter = paramString.length - 1; counter>=0; counter--) {
- [reversed appendFormat:@"%c", [paramString characterAtIndex:counter]];
- }
- return [reversed copy];
- }
步骤四:实现customActivity方法
首先customActivity方法中创建一组NSArray类型的字符串对象itemsToShare和TRStringReverseActivity对象stringReverseActivity,代码如下所示:
- - (IBAction)customActivity
- {
- NSArray *itemsToShare = @[@"Hello", @"World", @"Haha", @"123456789"];
- TRStringReverseActivity *stringReverseActivity = [[TRStringReverseActivity alloc]init];
- }
然后创建UIActivityViewController对象,使用initWithActivityItems: applicationActivities:方法进行初始化,itemsToShare对象和stringReverseActivity对象分别作为activityItems参数和applicationActivities参数,最后通过present方法显示出来,代码如下所示:
- - (IBAction)customActivity
- {
- NSArray *itemsToShare = @[@"Hello", @"World", @"Haha", @"123456789"];
- TRStringReverseActivity *stringReverseActivity = [[TRStringReverseActivity alloc]init];
- UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:itemsToShare applicationActivities:@[stringReverseActivity]];
- [self presentViewController:activityVC animated:YES completion:nil];
- }
运行程序点击自定义按钮,从应用底部出现分享框,如图-7所示:
图-7
点击返转服务按钮,界面弹出alertView对话框,并将字符串返转显示出来,如图-8所示:
图-8
2.4 完整代码
本案例中,TRViewController.m文件中的完整代码如下所示:
- #import "TRViewController.h"
- #import "TRStringReverseActivity.h"
- @interface TRViewController ()
- @property (weak, nonatomic) IBOutlet UITextField *textField;
- @end
- @implementation TRViewController
- - (IBAction)shared
- {
- UIActivityViewController * activityVC = [[UIActivityViewController alloc]initWithActivityItems:@[self.textField.text] applicationActivities:nil];
- //设置不包含的activity
- activityVC.excludedActivityTypes = @[UIActivityTypeCopyToPasteboard];
- [self presentViewController:activityVC animated:YES completion:nil];
- }
- - (IBAction)customActivity
- {
- NSArray *itemsToShare = @[@"Hello", @"World", @"Haha", @"123456789"];
- TRStringReverseActivity *stringReverseActivity = [[TRStringReverseActivity alloc]init];
- UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:itemsToShare applicationActivities:@[stringReverseActivity]];
- [self presentViewController:activityVC animated:YES completion:nil];
- }
- @end
本案例中,TRStringReverseActivity.m文件中的完整代码如下所示:
- #import "TRStringReverseActivity.h"
- @interface TRStringReverseActivity () <UIAlertViewDelegate>
- @property (strong, nonatomic) NSMutableArray *activityItems;
- @end
- @implementation TRStringReverseActivity
- //服务的类型
- - (NSString *)activityType
- {
- return [[NSBundle mainBundle].bundleIdentifier stringByAppendingFormat:@".%@", NSStringFromClass([self class])];
- }
- //显示在分享框中的服务的名称
- - (NSString *)activityTitle
- {
- return @"返转";
- }
- //显示在分享框的服务的图片
- - (UIImage *)activityImage
- {
- return [UIImage imageNamed:@"random"];
- }
- //是否显示分享按钮
- - (BOOL)canPerformWithActivityItems:(NSArray *)activityItems
- {
- for (id object in activityItems) {
- if ([object isKindOfClass:[NSString class]]) {
- return YES;
- }
- }
- return NO;
- }
- //解析分享数据时调用
- - (void)prepareWithActivityItems:(NSArray *)activityItems
- {
- NSMutableArray *stringObjects = [[NSMutableArray alloc]init];
- for (id object in activityItems) {
- if ([object isKindOfClass:[NSString class]]) {
- [stringObjects addObject:object];
- }
- }
- self.activityItems = stringObjects;
- }
- //执行服务,根据自己的应用做相应的处理
- - (void)performActivity
- {
- NSMutableString *reverseStrings = [[NSMutableString alloc]init];
- //反转字符串
- for (NSString *string in self.activityItems) {
- [reverseStrings appendString:[self reverseString:string]];
- [reverseStrings appendString:@"\n"];
- }
- UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"字符串返转" message:reverseStrings delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil];
- [alert show];
- }
- - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
- {
- [self activityDidFinish:YES];
- }
- - (NSString *)reverseString:(NSString *)paramString
- {
- NSMutableString *reversed = [[NSMutableString alloc]init];
- for (NSInteger counter = paramString.length - 1; counter>=0; counter--) {
- [reversed appendFormat:@"%c", [paramString characterAtIndex:counter]];
- }
- return [reversed copy];
- }
- @end
3 使用URL实现应用间的通信
3.1 问题
如果一个应用程序支持一些已知类型的URL,就可以通过对应的URL模式和该程序进行通讯,本案例使用URL实现应用间的通信,如图-9所示:
图-9
3.2 方案
首先在创建一个项目iac_source,在Storyboard场景中拖放一个Button控件,标题设置为“go to target”,并将Button关联成ViewController的方法click:。在click:方法中先制定一个通信的url类型iac。
其次创建一个项目iac_target,在项目配置的plist文件中声明支持url类型为iac,即iac_source中定义的url类型。
然后在程序iac_source中的viewDidLoad方法中使用UIApplication的openURL:方法实现应用间的跳转,URL是一个NSURL类型的参数。
最后在程序iac_target中响应,通过程序iac_source传递过来的URL信息在方法application:openURL:sourceApplication:annotation:中解析,该方法每次运行程序时都会被调用。
3.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义url类型
首先在创建一个项目iac_source,在Storyboard场景中拖放一个Button控件,标题设置为“go to target”,并将Button关联成ViewController的方法click:。在click:方法中先制定一个通信的url类型iac,代码如下所示:
- - (IBAction)click:(UIButton *)sender {
- NSURL *url = [NSURL URLWithString:@"iac://function/addContact?name=apple&age=18"];
- }
步骤二:在目标应用中声明支持的url类型
首先创建一个项目iac_target,在项目配置的plist文件中声明支持url类型为iac,即iac_source中定义的url类型。
展开 resources选择<app>info.plist,鼠标右击information property list ,然后从列表中选择URL types,右击 add row 添加一个对象(item)右击item add row ,从列表中选URL Schemes 再右击添加一个对象(item0),将item0的值设置为iac,如图-10所示:
图-10
步骤三:实现应用间的跳转
在程序iac_source中的viewDidLoad方法中使用UIApplication的openURL:方法实现应用间的跳转,代码如下所示:
- - (IBAction)click:(UIButton *)sender {
- NSURL *url = [NSURL URLWithString:@"iac://function/addContact?name=apple&age=18"];
- [[UIApplication sharedApplication]openURL:url];
- }
步骤四:响应并解析数据
在程序iac_target中响应,通过程序iac_source传递过来的URL信息在方法application:openURL:sourceApplication:annotation:中解析,openURL参数就是传递过来的url信息,该方法每次运行程序时都会被调用。
本案例实现根据传递过来的url参数,修改界面上Label的显示内容,首先在iac_target项目中的Storyboard界面拖拽一个Label控件,并关联成ViewController的属性name,代码如下所示:
- @interface ViewController ()
- @property (weak, nonatomic) IBOutlet UILabel *name;
- @end
其次在AppDelegate里面定义一个NSString类型的属性name,代码如下所示:
- @interface AppDelegate : UIResponder <UIApplicationDelegate>
- @property (strong, nonatomic) UIWindow *window;
- @property (nonatomic,copy)NSString *name;
- @end
然后在ViewController类中使用观察者模式,监听AppDelegate的name属性的改变,当name属性发生改变时,就修改界面Label的显示内容,代码如下所示:
- -(void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
- self.app = [UIApplication sharedApplication].delegate;
- self.name.text = self.app.name;
- [self.app addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
- }
- -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
- self.name.text = self.app.name;
- }
- -(void)viewWillDisappear:(BOOL)animated {
- [self.app removeObserver:self forKeyPath:@"name"];
- }
最后application:openURL:sourceApplication:annotation:方法解析url数据,获取到url中的参数信息,修改name属性的值,代码如下所示:
- -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
- if ([[url scheme] isEqualToString:@"iac"]) {
- NSMutableDictionary * parasDict = [@{} mutableCopy];
- //获取url的参数
- NSString * query = [url query];
- //将参数字符串用“&”分割
- NSArray * paras = [query componentsSeparatedByString:@"&"];
- //每一个参数用“=”分割
- for (NSString * para in paras) {
- NSArray * paraItems = [para componentsSeparatedByString:@"="];
- NSString * key = paraItems[0];
- NSString * value = paraItems[1];
- [parasDict setObject:value forKey:key];
- }
- //修改name属性
- self.name = [parasDict valueForKey:@"name"];
- }
- return YES;
- }
3.4 完整代码
本案例中,iac_source项目中的ViewController.m文件中的完整代码如下所示:
- #import "ViewController.h"
- @implementation ViewController
- - (IBAction)click:(UIButton *)sender {
- NSURL *url = [NSURL URLWithString:@"iac://function/addContact?name=apple&age=18"];
- [[UIApplication sharedApplication]openURL:url];
- }
- @end
本案例中,iac_target项目中的AppDelegate.h文件中的完整代码如下所示:
- #import <UIKit/UIKit.h>
- @interface AppDelegate : UIResponder <UIApplicationDelegate>
- @property (strong, nonatomic) UIWindow *window;
- @property (nonatomic,copy)NSString *name;
- @end
本案例中,iac_target项目中的AppDelegate.m文件中的完整代码如下所示:
- #import "AppDelegate.h"
- @implementation AppDelegate
- -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
- if ([[url scheme] isEqualToString:@"iac"]) {
- NSMutableDictionary * parasDict = [@{} mutableCopy];
- //获取url的参数
- NSString * query = [url query];
- //将参数字符串用“&”分割
- NSArray * paras = [query componentsSeparatedByString:@"&"];
- //每一个参数用“=”分割
- for (NSString * para in paras) {
- NSArray * paraItems = [para componentsSeparatedByString:@"="];
- NSString * key = paraItems[0];
- NSString * value = paraItems[1];
- [parasDict setObject:value forKey:key];
- }
- //修改name属性
- self.name = [parasDict valueForKey:@"name"];
- }
- return YES;
- }
- @end
本案例中,iac_target项目中的ViewController.m文件中的完整代码如下所示:
- #import "ViewController.h"
- #import "AppDelegate.h"
- @interface ViewController ()
- @property (weak, nonatomic) IBOutlet UILabel *name;
- @property (nonatomic,assign)AppDelegate *app;
- @end
- @implementation ViewController
- -(void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
- self.app = [UIApplication sharedApplication].delegate;
- self.name.text = self.app.name;
- [self.app addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
- }
- -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
- self.name.text = self.app.name;
- }
- -(void)viewWillDisappear:(BOOL)animated {
- [self.app removeObserver:self forKeyPath:@"name"];
- }
- @end
通知(Notification) 、 应用间通信(一)的更多相关文章
- 10-IOSCore - 应用间通信、本地通知
一.应用间通信 URL 调用系统服务: tel:11111 sms:xxx@163.com http:// URL深入 类型://主机:端口/地址?参数 label框等于文字大小快捷键:command ...
- 《java多线程编程核心技术》不使用等待通知机制 实现线程间通信的 疑问分析
不使用等待通知机制 实现线程间通信的 疑问分析 2018年04月03日 17:15:08 ayf 阅读数:33 编辑 <java多线程编程核心技术>一书第三章开头,有如下案例: ...
- 线程间通信 GET POST
线程间通信有三种方法:NSThread GCD NSOperation 进程:操作系统里面每一个app就是一个进程. 一个进程里面可以包含多个线程,并且我们每一个app里面有且仅有一 ...
- 浏览器桌面通知Notification探究
首先说明,这篇博文不是科普讲解的,而是立flag研究的,是关于浏览器消息自动推送,就是下面这个玩意: 最近常常在浏览器看到这样的消息推送,还有QQ.com的推送,现在我对这个不了解,不知道叫消息自动推 ...
- UWP开源项目 LLQNotifier 页面间通信利器(移植EventBus)
前言 EventBus是一个Android版本的页面间通信库,这个库让页面间的通信变得十分容易且大幅降低了页面之间的耦合.小弟之前玩Android的时候就用得十分顺手,现在玩uwp就觉得应该在这平台也 ...
- 系统间通信(5)——IO通信模型和JAVA实践 下篇
7.异步IO 上面两篇文章中,我们分别讲解了阻塞式同步IO.非阻塞式同步IO.多路复用IO 这三种IO模型,以及JAVA对于这三种IO模型的支持.重点说明了IO模型是由操作系统提供支持,且这三种IO模 ...
- Java多线程编程核心技术---线程间通信(二)
通过管道进行线程间通信:字节流 Java提供了各种各样的输入/输出流Stream可以很方便地对数据进行操作,其中管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据,一个线程发送 ...
- Java多线程编程核心技术---线程间通信(一)
线程是操作系统中独立的个体,但这些个体如果不经过特殊处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一.线程间通信可以使系统之间的交互性更强大,在大大提高CPU利用率的同时还会使程序员对各 ...
- java多线程系列5-死锁与线程间通信
这篇文章介绍java死锁机制和线程间通信 死锁 死锁:两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象. 同步代码块的嵌套案例 public class MyLock { // 创建两 ...
- Java并发——使用Condition线程间通信
线程间通信 线程之间除了同步互斥,还要考虑通信.在Java5之前我们的通信方式为:wait 和 notify.Condition的优势是支持多路等待,即可以定义多个Condition,每个condit ...
随机推荐
- Android 适配器
Adapter是连接后端数据和前端显示的桥梁,是数据和UI(View)之间的纽带. 在常见的View(ListView,GridView)等地方都需要用到Adapter.数据.Adapter ...
- 一段linux shell 代码涉及for循环和if esle
if [ 0 -ne $# ]; then echo "USAGE: prog [IN]input_file" >&2; exit 1;fisource /etc/p ...
- c# 关键字delegate、event(委托与事件)[MSDN原文摘录][2]
//Demo1:Declaring an event in an interface and implementing it in //a class. // event_keyword.cs usi ...
- BZOJ3696 化合物
我们可以树形dp... 令f[p][d]表示以p为根的子树,与p距离为d的结点数 然后我们计算答案: 一种是从某个节点q到根p的方案,对和为d的贡献是1 另一种是p的一个子树中的节点x到另一个子树中的 ...
- 生JS实现jQuery的ready方法呢?下面是其中之一的做法:
function ready(fn){ if(document.addEventListener){ //标准浏览器 document.addEventListener('DOMConten ...
- [转]iOS/iphone开发如何为苹果开发者帐号APPID续费
原文地址:http://blog.sina.com.cn/s/blog_68661bd80101nme6.html 其实相当的简单,这篇内容是给财务看的,有的地方连我自己看了都感觉有点...但如果不详 ...
- 个人收集的一些网页上一键云DDOS攻击的网站、IP地址测试,服务器压力测试
http://bbs.itzmx.com/thread-9018-1-1.html #1 - Network Stresser - http://networkstresser.com#2 - Lif ...
- ACM心情总结
已经快要12点了,然而还有5000字概率论论文没有动.在论文里,我本来是想要总结一下ACM竞赛中出现过的概率论题目,然而当敲打第一段前言的时候,我就迟疑了. 我问自己,ACM竞赛到底有什么现实意义. ...
- 远程连接Windows2008R2时服务器报Terminal Services错误的解决办法
症状: 使用终端服务客户端连接到Windows Server2008 R2的机器时,如果客户端选项中选择了打印机(注1)时,它可能会在在系统事件日志中记录一个TerminalServices打印机错误 ...
- C#操作Access数据库(创建&修改结构)
本文转自:http://www.cnblogs.com/liyugang/archive/2012/11/17/2775393.html 想要在程序中控制Access,不是数据,而是Access数据库 ...