ReactiveCocoa那些干货——2

来源:互联网 发布:js 双引号字符转义 编辑:程序博客网 时间:2024/05/16 15:08


前言:

笔者在之前的某个项目中由于需求调用系统摄像机,于是在此条件下封装了一个RAC关于UIImagePickerController的一个Category,以RAC框架中对UIImagePickerController的Category封装为提前,对UIImagePickerController进行了二次封装。

 

UIImagePickerController+RACSignalSupport介绍

     首先,让我们来看一下RACSignalSupport拓展中对UIImagePickerController所做的事情吧,如下:

       

 

通过RAC的源码可以看出来,在UIImagePickerController跟之前笔者提及的UIAlertView封装是类似的,同样是对委托进行拦截,原理这里就不多做说明,不清楚的童鞋可以回头看看之前的博文。

 

关于RAC对UIImagePickerController的这个Category,笔者早在2015年初的时候就使用过,但是使用之初就发现这个Category对imagePickerControllerDidCancel: 的拦截在某些情况下有些限制的,源码中,takeUntil:方法试图拦截imagePickerControllerDidCancel:的信号,思路上是正确的,但是某些情况下这个拦截会失灵,因此,笔者很干脆的将这个委托另外抽出了一个Category进行封装,这个Category是控制器(UIViewController的Category)。

        

并且实现如下:

 

- (RACSignal*)rac_willCancelSignalForImagePickerController:(UIImagePickerController*)imagePickerController {

   

    if (![selfcheckImagePickerController:imagePickerController]){

        return nil;

    }

    return [RACSignalcreateSignal:^RACDisposable*(id<RACSubscriber>subscriber) {

      

       [[[imagePickerController.rac_delegateProxysignalForSelector:@selector(imagePickerControllerDidCancel:)]deliverOn:[RACSchedulermainThreadScheduler]]subscribeNext:^(idx) {

           [subscriber sendNext:x];

           [subscriber sendCompleted];

        }];

        return nil;

    }];

}

思路是:通过统一截取Delegate的方法,截取imagePickerControllerDidCancel:这个回调的方法,并组建信号管道,将点击到Cancel的信号逐级传递。

 

在Category中先添加如下的Cancel信号处理

@weakify(self);

        [[selfrac_willCancelSignalForImagePickerController:imagePickerController]subscribeNext:^(idx) {

            @strongify(self);

            [selfcameraDeviceDismissViewControllerForAnimated:YEScompletion:dismissCompletion];

        }];

 

 

 

然后在需要创建系统相册/摄像机的地方进行调用

[[[selfopenCameraDeviceForDeviceType:kSystemAnimationTypePhotowithCompletion:^(UIImagePickerController *imagePickerController) {

             @strongify(self);

            [selfpresentViewController:imagePickerControlleranimated:YEScompletion:^{

               

            }];

        } dismissCompletion:^{

            //这里是点击Canceldismiss控制器完成后调用的block           

 

        }] deliverOn:[RACSchedulermainThreadScheduler]]subscribeNext:^(NSDictionary*dic) {

            NSLog(@"dic: %@", dic);

            UIImage*image = dic[@"UIImagePickerControllerEditedImage"];

            NSLog(@"image: %@", image);

            [selfcameraDeviceDismissViewControllerForAnimated:YEScompletion:^{

               

            }];

        }];

 

 

总结:

       关于RAC对于UIKit的封装,笔者的理解是可以将它看成一个拼图,不管是基于RAC的封装Category进行的二次封装也好,或者直接使用RACDelegateProxy进行的封装也好,都是从源头上获取事件,将其包装为一个Signal由开发者所组装的管道,进行的信号传递,最后修改变更视觉上的UI的过程,这也是RAC框架最为棒的核心概念响应式编程。笔者后面还会陆续有些文章,之后也会陆续介绍些自己对RAC核心类的理解,也希望各位对RAC框架有更多了解的大神们可以多多指教~


0 0