瑞昌市环保局网站建设,Wordpress 防注入代码,南通网络科技有限公司,平面设计速成培训机构RAC#xff08;ReactiveCocoa#xff09; 文章目录RAC#xff08;ReactiveCocoa#xff09;响应式编程和函数式编程的区别函数式编程响应式编程响应式编程的优点RAC操作1.利用button点击实现点击事件和传值2.RACSignal用法RACSignal总结#xff1a;3.对于label的TapGestur…RACReactiveCocoa 文章目录RACReactiveCocoa响应式编程和函数式编程的区别函数式编程响应式编程响应式编程的优点RAC操作1.利用button点击实现点击事件和传值2.RACSignal用法RACSignal总结3.对于label的TapGesture和KVO测试4.对textField的监听即过滤操作5.RAC过滤操作6.RAC映射操作7.RAC组合操作8.RAC定时器实现倒计时RAC的源码分析1.信号产生2.订阅信号3.发送信号4. 销毁ReactiveCocoa简称为RAC,响应式框架,是由Github开源的一个应用于iOS和OS开发的新框架,Cocoa是苹果整套框架的简称因此很多苹果框架喜欢以Cocoa结尾。在我们iOS开发过程中经常会响应某些事件来处理某些业务逻辑例如按钮的点击上下拉刷新网络请求属性的变化通过KVO或者用户位置的变化通过CoreLocation。但是这些事件都用不同的方式来处理比如action、delegate、KVO、callback(回调)等。其实这些事件都可以通过RAC处理ReactiveCocoa为事件提供了很多处理方法而且利用RAC处理事件很方便可以把要处理的事情和监听的事情的代码放在一起这样非常方便我们管理就不需要跳到对应的方法里。非常符合我们开发中高聚合低耦合的思想。响应式编程和函数式编程的区别 
函数式编程 1.如果想再去调用别的方法那么就需要返回一个对象 2.如果想用()去执行那么需要返回一个block 3.如果想让返回的block再调用对象的方法那么这个block就需要返回一个对象即返回值为一个对象的block。 4.高阶函数在函数式编程中把函数当参数来回传递而这个说成术语我们把他叫做高阶函数。在oc中blocks是被广泛使用的参数传递它实际上是匿名函数。 响应式编程 1.响应式编程是一种和事件流有关的编程模式关注导致状态值改变的行为事件一系列事件组成了事件流。 2.一系列事件是导致属性值发生变化的原因。FRP非常类似于设计模式里的观察者模式。 3.FRP与普通的函数式编程相似但是每个函数可以接收一个输入值的流如果其中一个新的输入值到达的话这个函数将根据最新的输入值重新计算并且产生一个新的输出。这是一种”数据流”编程模式。 响应式编程的优点 1 开发过程中状态以及状态之间依赖过多,RAC更加有效率地处理事件流而无需显式去管理状态。在OO或者过程式编程中状态变化是最难跟踪最头痛的事。这个也是最重要的一点。 2 减少变量的使用由于它跟踪状态和值的变化因此不需要再申明变量不断地观察状态和更新值。 3 提供统一的消息传递机制将oc中的通知actionKVO以及其它所有UIControl事件的变化都进行监控当变化发生时就会传递事件和值。 4 当值随着事件变换时可以使用mapfilterreduce等函数便利地对值进行变换操作。 RAC操作 
1.利用button点击实现点击事件和传值 
//  MainViewController.m
- (void)addButton {   //button点击和传值self.firstButton  [UIButton buttonWithType:UIButtonTypeRoundedRect];self.firstButton.frame  CGRectMake(0, 0, 100, 100);[self.firstButton setTitle:未获 forState:UIControlStateNormal];self.firstButton.backgroundColor  [UIColor purpleColor];[self.view addSubview:self.firstButton];[[self.firstButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {SecondViewController *secondViewController  [[SecondViewController alloc] init];secondViewController.modalPresentationStyle  UIModalPresentationFullScreen;secondViewController.subject  [RACSubject subject];[secondViewController.subject subscribeNext:^(id x) {NSLog(%,x);[self.firstButton setTitle:x forState:UIControlStateNormal];}];[self presentViewController:secondViewController animated:YES completion:nil];}];
}//  SecondViewController.m
self.backButton  [UIButton buttonWithType:UIButtonTypeRoundedRect];self.backButton.backgroundColor  [UIColor redColor];self.backButton.frame  CGRectMake(0, 0, 100, 100);[self.backButton setTitle:返回 forState:UIControlStateNormal];[self.view addSubview:self.backButton];[[self.backButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {[self.subject sendNext:已获];[self dismissViewControllerAnimated:YES completion:nil];}]; 
效果展示   
2.RACSignal用法 
// 1.创建信号RACSignal *signal  [RACSignal createSignal:^RACDisposable *(idRACSubscriber subscriber) {// 3.发送信号[subscriber sendNext:牛逼];[subscriber sendNext:牛逼2];// 4.取消信号如果信号想要被取消就必须返回一个RACDisposable// 信号什么时候被取消1.自动取消当一个信号的订阅者被销毁的时候机会自动取消订阅2.手动取消//block什么时候调用一旦一个信号被取消订阅就会调用//block作用当信号被取消时用于清空一些资源return [RACDisposable disposableWithBlock:^{NSLog(取消订阅);}];}];// 2. 订阅信号// subscribeNext// 把nextBlock保存到订阅者里面// 只要订阅信号就会返回一个取消订阅信号的类RACDisposable *disposable  [signal subscribeNext:^(id x) {// block的调用时刻只要信号内部发出数据就会调用这个blockNSLog(%, x);}];// 取消订阅[disposable dispose];输出  
RACSignal总结 
一.核心1.核心信号类2.信号类的作用只要有数据改变就会把数据包装成信号传递出去3.只要有数据改变就会有信号发出4.数据发出并不是信号类发出信号类不能发送数据
二.使用方法1.创建信号2.订阅信号
三.实现思路1.当一个信号被订阅创建订阅者并把nextBlock保存到订阅者里面。2.创建的时候会返回 [RACDynamicSignal createSignal:didSubscribe];3.调用RACDynamicSignal的didSubscribe4.发送信号[subscriber sendNext:value];5.拿到订阅者的nextBlock调用3.对于label的TapGesture和KVO测试 
- (void)addKVOandTapGesture {   //对于label的TapGesture和KVO测试self.firstLabel  [[UILabel alloc] init];self.firstLabel.text  未点击;self.firstLabel.frame  CGRectMake(0, 100, 100, 100);[self.view addSubview:self.firstLabel];UITapGestureRecognizer *tap  [[UITapGestureRecognizer alloc] init];self.firstLabel.userInteractionEnabled  YES;[self.firstLabel addGestureRecognizer:tap];[tap.rac_gestureSignal subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {self.firstLabel.text  [NSString stringWithFormat:%d, arc4random()];}];//KVO[RACObserve(self, self.firstLabel.text) subscribeNext:^(id  _Nullable x) {NSLog(%, x);}];[[self.firstLabel.text rac_valuesAndChangesForKeyPath:text options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {NSLog(%, x);}];
}4.对textField的监听即过滤操作 
self.firstTextField  [[UITextField alloc] init];self.firstTextField.backgroundColor  [UIColor orangeColor];[self.view addSubview:self.firstTextField];self.firstTextField.frame  CGRectMake(100, 100, 200, 30);[self.firstTextField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {NSLog(%, x);}];// 只有当文本框的内容长度大于5才获取文本框里的内容[[self.firstTextField.rac_textSignal filter:^BOOL(id value) {// value 源信号的内容return [value length]  5;// 返回值 就是过滤条件。只有满足这个条件才能获取到内容}] subscribeNext:^(id x) {NSLog(已过滤-----%, x);}];输出  
5.RAC过滤操作 
#pragma mark RACSubject过滤- (void)skipRACSubject {// 跳跃  如下skip传入2 跳过前面两个值// 实际用处 在实际开发中比如 后台返回的数据前面几个没用我们想跳跃过去便可以用skipRACSubject *subject  [RACSubject subject];[[subject skip:2] subscribeNext:^(id x) {NSLog(%, x);}];[subject sendNext:1];[subject sendNext:2];[subject sendNext:3];
}- (void)distinctUntilChangedRACSubject {//distinctUntilChanged:-- 如果当前的值跟上一次的值一样就不会被订阅到RACSubject *subject  [RACSubject subject];[[subject distinctUntilChanged] subscribeNext:^(id x) {NSLog(%, x);}];// 发送信号[subject sendNext:1];[subject sendNext:2];[subject sendNext:2]; // 不会被订阅
}- (void)takeRACSubject {// take:可以屏蔽一些值,去前面几个值---这里take为2 则只拿到前两个值RACSubject *subject  [RACSubject subject];[[subject take:2] subscribeNext:^(id x) {NSLog(%, x);}];// 发送信号[subject sendNext:1];[subject sendNext:2];[subject sendNext:3];
}- (void)takeLastRACSubject {//takeLast:和take的用法一样不过他取的是最后的几个值如下则取的是最后两个值//注意点:takeLast 一定要调用sendCompleted告诉他发送完成了这样才能取到最后的几个值RACSubject *subject  [RACSubject subject];[[subject takeLast:2] subscribeNext:^(id x) {NSLog(%, x);}];// 发送信号[subject sendNext:1];[subject sendNext:2];[subject sendNext:3];[subject sendCompleted];
}- (void)ignoreRACSubject {//ignore:忽略一些值//ignoreValues:表示忽略所有的值// 1.创建信号RACSubject *subject  [RACSubject subject];// 2.忽略一些值RACSignal *ignoreSignal  [subject ignore:2]; // ignoreValues:表示忽略所有的值// 3.订阅信号[ignoreSignal subscribeNext:^(id x) {NSLog(%, x);}];// 4.发送数据[subject sendNext:2];}6.RAC映射操作 
- (void)map {// 创建信号RACSubject *subject  [RACSubject subject];// 绑定信号RACSignal *bindSignal  [subject map:^id(id value) {// 返回的类型就是你需要映射的值return [NSString stringWithFormat:ws:%, value]; //这里将源信号发送的“123” 前面拼接了ws}];// 订阅绑定信号[bindSignal subscribeNext:^(id x) {NSLog(%, x);}];// 发送信号[subject sendNext:123];}- (void)flatMap {// 创建信号RACSubject *subject  [RACSubject subject];// 绑定信号RACSignal *bindSignal  [subject flattenMap:^RACStream *(id value) {// block只要源信号发送内容就会调用// value: 就是源信号发送的内容// 返回信号用来包装成修改内容的值return [RACReturnSignal return:value];}];// flattenMap中返回的是什么信号订阅的就是什么信号(那么x的值等于value的值如果我们操纵value的值那么x也会随之而变)// 订阅信号[bindSignal subscribeNext:^(id x) {NSLog(%, x);}];// 发送数据[subject sendNext:123];
}- (void)flattenMap2 {// flattenMap 主要用于信号中的信号// 创建信号RACSubject *signalofSignals  [RACSubject subject];RACSubject *signal  [RACSubject subject];// 订阅信号//方式1//    [signalofSignals subscribeNext:^(id x) {////        [x subscribeNext:^(id x) {//            NSLog(%, x);//        }];//    }];// 方式2//    [signalofSignals.switchToLatest  ];// 方式3//   RACSignal *bignSignal  [signalofSignals flattenMap:^RACStream *(id value) {////        //value:就是源信号发送内容//        return value;//    }];//    [bignSignal subscribeNext:^(id x) {//        NSLog(%, x);//    }];// 方式4--------也是开发中常用的[[signalofSignals flattenMap:^RACStream *(id value) {return value;}] subscribeNext:^(id x) {NSLog(%, x);}];// 发送信号[signalofSignals sendNext:signal];[signal sendNext:123];
}7.RAC组合操作 
#pragma mark 组合
// 把多个信号聚合成你想要的信号,使用场景----比如-当多个输入框都有值的时候按钮才可点击。
// 思路--- 就是把输入框输入值的信号都聚合成按钮是否能点击的信号。
- (void)combineLatest {RACSignal *combinSignal  [RACSignal combineLatest:[self.firstTextField.rac_textSignal, self.secondTextField.rac_textSignal] reduce:^id(NSString *account, NSString *pwd){ //reduce里的参数一定要和combineLatest数组里的一一对应。// block: 只要源信号发送内容就会调用组合成一个新值。NSLog(% %, account, pwd);return (account.length  pwd.length);}];//        // 订阅信号
//        [combinSignal subscribeNext:^(id x) {
//            self.combinationButton.enabled  [x boolValue];
//        }];    // ----这样写有些麻烦可以直接用RAC宏RAC(self.combinationButton, enabled)  combinSignal;
}- (void)zipWith {//zipWith:把两个信号压缩成一个信号只有当两个信号同时发出信号内容时并且把两个信号的内容合并成一个元祖才会触发压缩流的next事件。// 创建信号ARACSubject *signalA  [RACSubject subject];// 创建信号BRACSubject *signalB  [RACSubject subject];// 压缩成一个信号// **-zipWith-**: 当一个界面多个请求的时候要等所有请求完成才更新UI// 等所有信号都发送内容的时候才会调用RACSignal *zipSignal  [signalA zipWith:signalB];[zipSignal subscribeNext:^(id x) {NSLog(%, x); //所有的值都被包装成了元组}];// 发送信号 交互顺序元组内元素的顺序不会变跟发送的顺序无关而是跟压缩的顺序有关[signalA zipWith:signalB]---先是A后是B[signalA sendNext:1];[signalB sendNext:2];
}// 任何一个信号请求完成都会被订阅到
// merge:多个信号合并成一个信号任何一个信号有新值就会调用
- (void)merge {// 创建信号ARACSubject *signalA  [RACSubject subject];// 创建信号BRACSubject *signalB  [RACSubject subject];//组合信号RACSignal *mergeSignal  [signalA merge:signalB];// 订阅信号[mergeSignal subscribeNext:^(id x) {NSLog(%, x);}];// 发送信号---交换位置则数据结果顺序也会交换[signalB sendNext:下部分];[signalA sendNext:上部分];
}// then --- 使用需求有两部分数据想让上部分先进行网络请求但是过滤掉数据然后进行下部分的拿到下部分数据
- (void)then {// 创建信号ARACSignal *signalA  [RACSignal createSignal:^RACDisposable *(idRACSubscriber subscriber) {// 发送请求NSLog(----发送上部分请求---afn);[subscriber sendNext:上部分数据];[subscriber sendCompleted]; // 必须要调用sendCompleted方法return nil;}];// 创建信号BRACSignal *signalsB  [RACSignal createSignal:^RACDisposable *(idRACSubscriber subscriber) {// 发送请求NSLog(--发送下部分请求--afn);[subscriber sendNext:下部分数据];return nil;}];// 创建组合信号// then;忽略掉第一个信号的所有值RACSignal *thenSignal  [signalA then:^RACSignal *{// 返回的信号就是要组合的信号return signalsB;}];// 订阅信号[thenSignal subscribeNext:^(id x) {NSLog(%, x);}];}// concat----- 使用需求有两部分数据想让上部分先执行完了之后再让下部分执行都可获取值
- (void)concat {// 组合// 创建信号ARACSignal *signalA  [RACSignal createSignal:^RACDisposable *(idRACSubscriber subscriber) {// 发送请求//        NSLog(----发送上部分请求---afn);[subscriber sendNext:上部分数据];[subscriber sendCompleted]; // 必须要调用sendCompleted方法return nil;}];// 创建信号BRACSignal *signalsB  [RACSignal createSignal:^RACDisposable *(idRACSubscriber subscriber) {// 发送请求//        NSLog(--发送下部分请求--afn);[subscriber sendNext:下部分数据];return nil;}];// concat:按顺序去链接//**-注意-**concat第一个信号必须要调用sendCompleted// 创建组合信号RACSignal *concatSignal  [signalA concat:signalsB];// 订阅组合信号[concatSignal subscribeNext:^(id x) {NSLog(%,x);}];}输出  
8.RAC定时器实现倒计时 
#pragma mark 定时器
- (void)countdown {self.timeButton  [UIButton buttonWithType:UIButtonTypeCustom];self.timeButton.frame  CGRectMake(200, 600, 100, 50);self.timeButton.backgroundColor  [UIColor yellowColor];[self.timeButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];[self.timeButton setTitle:发送验证码 forState:UIControlStateNormal];[self.view addSubview:self.timeButton];[[self.timeButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {self.count  10;self.timeButton.enabled  NO;[self.timeButton setTitle:[NSString stringWithFormat:%d, self.count] forState:UIControlStateNormal];self.disposable  [[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]]subscribeNext:^(id x) {if (self.count  1) {[self.timeButton setTitle:[NSString stringWithFormat:重新发送] forState:UIControlStateNormal];self.timeButton.enabled  YES;[self.disposable dispose];} else {self.count--;[self.timeButton setTitle:[NSString stringWithFormat:%d, self.count] forState:UIControlStateNormal];NSLog(%d,self.count);}}];}];}RAC的源码分析 
1.信号产生 //1. RACSignal(RACSignal *)createSignal:(RACDisposable * (^)(idRACSubscriber subscriber))didSubscribe {//把block封装进来 利用多态原理返回 RACDynamicSignalreturn [RACDynamicSignal createSignal:didSubscribe];//传入的参数就是一个block
}//2.RACDynamicSignal(RACSignal *)createSignal:(RACDisposable * (^)(idRACSubscriber subscriber))didSubscribe {RACDynamicSignal *signal  [[self alloc] init];// 绑定block,在订阅信号的时候调用signal-_didSubscribe  [didSubscribe copy];return [signal setNameWithFormat:createSignal:];
} 
2.订阅信号 // 1.RACSignal
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {NSCParameterAssert(nextBlock ! NULL);//产生一个订阅者 绑定nextBlock RACSubscriber *o  [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];//这是self 是RACDynamicSignal 是本方法的调用者return [self subscribe:o];
}// 2.RACSubscriber
- (RACDisposable *)subscribe:(idRACSubscriber)subscriber {NSCParameterAssert(subscriber ! nil);
// 产生 RACCompoundDisposable : 核心销毁者RACCompoundDisposable *disposable  [RACCompoundDisposable compoundDisposable];// RACPassthroughSubscriber 核心订阅者/*subscriber : 订阅者signal : RACDynamicSignal 信号disposable : 销毁者传入者三个参数后 分别用三个属性保存住三个属性保存住 是为了后续使用*/subscriber  [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];if (self.didSubscribe ! NULL) {// RACScheduler(封装了一个GCD)RACDisposable *schedulingDisposable  [RACScheduler.subscriptionScheduler schedule:^{//把核心订阅者传出去了,  这里的subscriber 就是create信号时block中的参数,订阅者//执行创建信号时保存的didSubscribeBlockRACDisposable *innerDisposable  self.didSubscribe(subscriber);//添加我的要销毁者的对象 把要销毁的对象都装进去 根据情况统一销毁[disposable addDisposable:innerDisposable];}];[disposable addDisposable:schedulingDisposable];}return disposable;
} 
订阅信号,产生了信号的一个订阅者,绑定nextBlock ,在下一步发送信号的时候调用这个nextBlock .产生一个核心销毁者(RACCompoundDisposable),产生一个核心订阅者(RACPassthroughSubscriber),核心订阅者保存了销毁者,1中创建的订阅者,以及信号.执行didSubscribe(subscriber) 
3.发送信号 
- (void)sendNext:(id)value {if (self.disposable.disposed) return;if (RACSIGNAL_NEXT_ENABLED()) {RACSIGNAL_NEXT(cleanedSignalDescription(self.signal), cleanedDTraceString(self.innerSubscriber.description), cleanedDTraceString([value description]));}
//真正的订阅 [self.innerSubscriber sendNext:value];
}
//RACSubscriber
- (void)sendNext:(id)value {//加锁synchronized (self) {void (^nextBlock)(id)  [self.next copy];if (nextBlock  nil) return;nextBlock(value);} 
4. 销毁 
在订阅信号的时候,产生了一个核心订阅者(RACPassthroughSubscriber)和一个核心销毁者(RACCompoundDisposable), 而核心订阅者内部持有了订阅者(subscriber),信号(signal),以及核心销毁者(disposable), 核心销毁者(disposable)可以被添加其他的销毁者,存入内部的一个数组中,在自身被释放的时候,会把数组中的也全部释放. 比如订阅者被self持有 
[subscriber sendNext:123];
self.subscriber  subscriber; 
要想释放掉信号相关的内存,就必须self.subscriber  nil. 当订阅者被释放,在dealloc方法中 
- (void)dealloc {
//核心销毁者开始执行dispose方法[self.disposable dispose];
} 
核心销毁者的dispose 
- (void)dispose {#if RACCompoundDisposableInlineCount//C 数组 type * a[2]RACDisposable *inlineCopy[RACCompoundDisposableInlineCount];#endifCFArrayRef remainingDisposables  NULL;pthread_mutex_lock(_mutex);{_disposed  YES;#if RACCompoundDisposableInlineCountfor (unsigned i  0; i  RACCompoundDisposableInlineCount; i) {inlineCopy[i]  _inlineDisposables[i];//当前的销毁数组,一个个的清理 数组移除_inlineDisposables[i]  nil;}#endifremainingDisposables  _disposables;_disposables  NULL;}pthread_mutex_unlock(_mutex);#if RACCompoundDisposableInlineCount// Dispose outside of the lock in case the compound disposable is used// recursively.for (unsigned i  0; i  RACCompoundDisposableInlineCount; i) {[inlineCopy[i] dispose];//存入的disposable各自调用各自的dispose方法}#endifif (remainingDisposables  NULL) return;CFIndex count  CFArrayGetCount(remainingDisposables);CFArrayApplyFunction(remainingDisposables, CFRangeMake(0, count), disposeEach, NULL);CFRelease(remainingDisposables);
}存进核心销毁者的各个disposable调用dispose方法 [RACDisposable dispose] 
- (void)dispose {void (^disposeBlock)(void)  NULL;
//遍历去找销毁对象while (YES) {void *blockPtr  _disposeBlock;
//        OSAtomicCompareAndSwapPtrBarrier(v1,v2,v3)/*v1 与 v3 匹配 相同就返回yes然后把v2 赋值给v3 也就是  null*/if (OSAtomicCompareAndSwapPtrBarrier(blockPtr, NULL, _disposeBlock)) {if (blockPtr ! (__bridge void *)self) {disposeBlock  CFBridgingRelease(blockPtr);}break;}}
//    持有的block,成为了临时变量,执行完,block也就释放了if (disposeBlock ! nil) disposeBlock();
} 
大佬博客 
RACdemo地址 文章转载自: http://www.morning.rchsr.cn.gov.cn.rchsr.cn http://www.morning.mkrjf.cn.gov.cn.mkrjf.cn http://www.morning.wjplm.cn.gov.cn.wjplm.cn http://www.morning.aswev.com.gov.cn.aswev.com http://www.morning.ntnml.cn.gov.cn.ntnml.cn http://www.morning.kmqjx.cn.gov.cn.kmqjx.cn http://www.morning.jcwrb.cn.gov.cn.jcwrb.cn http://www.morning.mcwgn.cn.gov.cn.mcwgn.cn http://www.morning.nbnq.cn.gov.cn.nbnq.cn http://www.morning.gqksd.cn.gov.cn.gqksd.cn http://www.morning.gnbtp.cn.gov.cn.gnbtp.cn http://www.morning.rbhcx.cn.gov.cn.rbhcx.cn http://www.morning.tplht.cn.gov.cn.tplht.cn http://www.morning.rcjqgy.com.gov.cn.rcjqgy.com http://www.morning.mnmrx.cn.gov.cn.mnmrx.cn http://www.morning.zdtfr.cn.gov.cn.zdtfr.cn http://www.morning.lsbjj.cn.gov.cn.lsbjj.cn http://www.morning.hpnhl.cn.gov.cn.hpnhl.cn http://www.morning.rszbj.cn.gov.cn.rszbj.cn http://www.morning.jwwfk.cn.gov.cn.jwwfk.cn http://www.morning.jyfrz.cn.gov.cn.jyfrz.cn http://www.morning.rdkt.cn.gov.cn.rdkt.cn http://www.morning.fqyqm.cn.gov.cn.fqyqm.cn http://www.morning.jhzct.cn.gov.cn.jhzct.cn http://www.morning.ymqrc.cn.gov.cn.ymqrc.cn http://www.morning.nqpy.cn.gov.cn.nqpy.cn http://www.morning.msgrq.cn.gov.cn.msgrq.cn http://www.morning.mgkb.cn.gov.cn.mgkb.cn http://www.morning.bqmsm.cn.gov.cn.bqmsm.cn http://www.morning.jwsrp.cn.gov.cn.jwsrp.cn http://www.morning.xzgbj.cn.gov.cn.xzgbj.cn http://www.morning.kgsws.cn.gov.cn.kgsws.cn http://www.morning.bxhch.cn.gov.cn.bxhch.cn http://www.morning.txtzr.cn.gov.cn.txtzr.cn http://www.morning.hpspr.com.gov.cn.hpspr.com http://www.morning.wwthz.cn.gov.cn.wwthz.cn http://www.morning.mstrb.cn.gov.cn.mstrb.cn http://www.morning.qyfrd.cn.gov.cn.qyfrd.cn http://www.morning.cgbgc.cn.gov.cn.cgbgc.cn http://www.morning.knryp.cn.gov.cn.knryp.cn http://www.morning.lthpr.cn.gov.cn.lthpr.cn http://www.morning.zzqgc.cn.gov.cn.zzqgc.cn http://www.morning.jfmjq.cn.gov.cn.jfmjq.cn http://www.morning.zwhtr.cn.gov.cn.zwhtr.cn http://www.morning.wlnr.cn.gov.cn.wlnr.cn http://www.morning.qggxt.cn.gov.cn.qggxt.cn http://www.morning.ykgp.cn.gov.cn.ykgp.cn http://www.morning.qyqdz.cn.gov.cn.qyqdz.cn http://www.morning.nzmhk.cn.gov.cn.nzmhk.cn http://www.morning.errnull.com.gov.cn.errnull.com http://www.morning.pggkr.cn.gov.cn.pggkr.cn http://www.morning.zlbjx.cn.gov.cn.zlbjx.cn http://www.morning.cfcdr.cn.gov.cn.cfcdr.cn http://www.morning.qjdqj.cn.gov.cn.qjdqj.cn http://www.morning.ffmx.cn.gov.cn.ffmx.cn http://www.morning.ftlgy.cn.gov.cn.ftlgy.cn http://www.morning.krqhw.cn.gov.cn.krqhw.cn http://www.morning.pcjw.cn.gov.cn.pcjw.cn http://www.morning.rfwkn.cn.gov.cn.rfwkn.cn http://www.morning.lfsmf.cn.gov.cn.lfsmf.cn http://www.morning.gtkyr.cn.gov.cn.gtkyr.cn http://www.morning.grbp.cn.gov.cn.grbp.cn http://www.morning.fykrm.cn.gov.cn.fykrm.cn http://www.morning.thnpj.cn.gov.cn.thnpj.cn http://www.morning.phnbd.cn.gov.cn.phnbd.cn http://www.morning.zqfjn.cn.gov.cn.zqfjn.cn http://www.morning.wtnyg.cn.gov.cn.wtnyg.cn http://www.morning.qpnmd.cn.gov.cn.qpnmd.cn http://www.morning.rjcqb.cn.gov.cn.rjcqb.cn http://www.morning.sgrdp.cn.gov.cn.sgrdp.cn http://www.morning.btjyp.cn.gov.cn.btjyp.cn http://www.morning.bhdyr.cn.gov.cn.bhdyr.cn http://www.morning.hwbmn.cn.gov.cn.hwbmn.cn http://www.morning.yybcx.cn.gov.cn.yybcx.cn http://www.morning.qwbls.cn.gov.cn.qwbls.cn http://www.morning.bsqkt.cn.gov.cn.bsqkt.cn http://www.morning.kzcz.cn.gov.cn.kzcz.cn http://www.morning.slzkq.cn.gov.cn.slzkq.cn http://www.morning.hcgbm.cn.gov.cn.hcgbm.cn http://www.morning.tpchy.cn.gov.cn.tpchy.cn