原创

RAC那些干货——3

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/block_xh/article/details/51603572

前言:

笔者之前的某篇博文中,简单介绍了通过RAC,缩减代码量,使得调用系统相册、相机更加简单遍历,本文中,笔者将就高度定制相册通过RAC的方法进行介绍,同时,笔者写了一个小Demo,可供大家参考,那么,闲话不多说了,开始今天的干货之旅吧~

 

 

Demo简介

关于关于本次笔者的博文中,有个小demo,先来介绍下吧!

 以上为demo的层结构,本demo里,笔者使用了cocoapods把依赖的RAC以及RACModel两个开源库pod到项目中,关于cocoapods这个神器,笔者这里就不多说了,总之是一个对import开源库帮助相当大的东西,节省了很多的时间,没用过或者没有接触过的童鞋有兴趣可自行百度下~

首先,项目中的主要构成有:宏文件、用于显示相册的Cell、用于处理数据的model、自定义相册的vc控制器、相关的拓展category

宏文件:定义了几个宏,方便使用;

用于显示的Cell:除了显示缩略图以及记录选中状态和某些小动画外,其他的不负责;

自定义相册控制器:本控制器分为两部分,一部分为base vc,用于处理collectionView相关,真正显示的custom vc则是真正用于显示相册的控制器;

相关拓展:这部分是本次中最重要的“肉戏”,关于rac的一些列封装以及在此基础上的调度都是在这部分内的;

 

 

核心逻辑构建说明

     

笔者有点懒,所以太详细的说明就不在这里经行啰嗦了,重点放在category里,现在来看下category里做了什么吧!

 category中主要包含UIViewControllerALAseetLibrary的拓展,即UIViewController+ALAsset

本范畴中,主要对ALAssetLibrary进行了封装,部分源码如下:

 

- (void)openPhotoLibraryWithALAssetType:(kALAssetType)type nextImageURLBlock:(void(^)(ALAsset *asset))block failureBlock:(void(^)(NSError*error))failureBlock completion:(void(^)())completion {

   

    [self enumerationResultsBlock:^(ALAssetsGroup *group) {

       

        [group enumerateAssetsUsingBlock:^(ALAsset *result,NSUInteger index, BOOL *stop) {

           

            if (result) {

               

                id object = [resultvalueForProperty:ALAssetPropertyType];

                NSString *typeString = [selfgetALAssetType:type];

               

                if([objectisEqualToString:typeString]) {

                    block(result);

                    if ((index +1) == number) {

                       completion();

                        number =0;

                    }

                }

            }

        }];

    } assetType:type];

}

上面的方法里,通过枚举了ALAssetLibrary,获取到资源库中的资源数据,也就是资源库中的ALAsset数据包,然后通过rac进行信息的传递。

 

- (RACSignal*)rac_openPhotoLibraryWithALAssetType:(kALAssetType)type {

   

    @weakify(self);

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

       

        @strongify(self);

       

        [self openPhotoLibraryWithALAssetType:type nextImageURLBlock:^(ALAsset *asset) {

           

            [subscriber sendNext:asset];

           

        } failureBlock:^(NSError *error) {

           

            [subscriber sendError:error];

            [subscriber sendCompleted];

 

        } completion:^{

           

            [subscriber sendCompleted];

           

        }];

        return nil;

    }];

}

接下去是最重要的HSYCustomPhotoViewController+RACSign范畴。这个范畴主要对HSYCustomPhotoViewController的委托进行了截取,通过rac进行信息的传递,部分源码如下:

- (RACSignal*)rac_didSelectCompletion {

 

    RACSignal *siganl = [[[self.rac_delegateProxy

                           signalForSelector:@selector(didSelectCompletionImages:)]

                          reduceEach:^(NSArray *images){

        return images;

    }] setNameWithFormat:@"%@-rac_didSelectCompletion",self.rac_description];

    RACUseDelegateProxy(self);

   

    return siganl;

}

这个方法是完全仿造rac对委托截取的范畴写法,通过截取HSYCustomPhotoViewController的委托动作,把所获取的图片或者其他资源的信息信号发送出去。

 

@protocol HSYCustomPhotoViewControllerDelegate <NSObject>

 

- (void)didSelectImage:(UIImage *)image;

- (void)didSelectCompletionImages:(NSArray *)images;

 

@end

上面的委托为HSYCustomPhotoViewController中的委托,第一个委托方法是获取单个图片,第二个是获取多选图片的资源。在rac范畴中,通过截取这个委托,实现以下的步骤:

@weakify(self);

    self.selectIndexPathCell = ^(idtableViewCell,NSIndexPath*indexPath) {

    

        @strongify(self);

        CustomPhotosCell *cell = (CustomPhotosCell *)tableViewCell;

        BOOL isAddObject = [celltransformsAnimation];

        [self.viewModelreloadDataForIsAddObject:isAddObject withIndex:indexPath.row];

    };

 

笔者在demo中对获取到的单个图片信息进行了处理,[self.viewModelreloadDataForIsAddObject:isAddObjectwithIndex:indexPath.row];方法中,笔者使用的是MVVM模式,也就是将数据处理抽出来,使用Model进行小封装,当然,如果是不习惯或者不使用这个方法的童鞋,也可以把数据混合到控制器中,由于笔者有比较严重的代码洁癖,不喜欢代码堆积,所以会对每个类的代码量经行控制以及不同层次的区分,关于MVVM模式,算是笔者个人很喜欢的一种设计模式,笔者这里就不多做叙述了,如果有兴趣的童鞋也可以自行百度相关资料,以后笔者有时间会单独出一期关于MVVMRAC结合使用的博客。

言归正传,上面说到在用于显示相册资源的vc控制器中的处理逻辑,下面说说怎么具体到只用一个方法就实现自定义。

HSYCustomPhotoViewController+CustomALAsset范畴中,笔者对ALAsset范畴和RAC范畴进行了结合,也就是二次的封装,到达可以只通过一个方法获取到数据,以下为源码:

+ (void)rac_openAssetPhotoResourcesLibraryWithAssetType:(kALAssetType)type presentBlock:(void(^)(UINavigationController *nav))block completion:(void(^)(idx))completion {

   

    HSYCustomPhotoViewController *vc = [[HSYCustomPhotoViewControlleralloc] initWithALAssetType:type];

    UINavigationController *nav = [[UINavigationControlleralloc] initWithRootViewController:vc];

    block(nav);

    [[[vc rac_didSelectCompletion]deliverOn:[RACSchedulermainThreadScheduler]] subscribeNext:^(id x) {

        completion(x);

    }];

}

上面的方法中,笔者通过二次封装中使用blockrac截取到的信号进行传递,使用也是相当的简单,只需要在需要present出控制器的地方去调用该方法,如:

- (void)presentCustomPhotosViewController:(UIButton *)button {

   

    @weakify(self);

    [HSYCustomPhotoViewControllerrac_openAssetPhotoResourcesLibraryWithAssetType:kALAssetTypePhotopresentBlock:^(UINavigationController *nav) {

        @strongify(self);

        //此处present出控制器

        [self presentViewController:nav animated:YEScompletion:^{

           

       }];

    } completion:^(id x) {

       //此处为获取到资源后的回调,笔者只用的是多选的情况,因此此处的回调会是一个数组,数组元素为选中的资源数据

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

    }];

}

 

以上就是本次笔者想要和大家分享的关于rac嵌套到自定义相册的使用方法,通过这一些列封装、二次封装,使得加载使用自定义相册变得更简单更快捷,只需要一个block方法,就可以达到目的。 

 

总结:

         本次的分享,笔者在demo中并未做过多的拓展,比如点击Cell获取看大图、高仿系统的做法现有一个文件夹列表等都未实现,因为笔者觉得这些都不是本次分享的重点,如果有需要或者有兴趣的童鞋也可以自己去拓展,demo中提供的可拓展性也比较大,大家可以根据需要进行深层次的封装哦!

PS: demo的获取地址https://yunpan.cn/OcRfthkBTpFAsA (提取码:cf8a) 

展开阅读全文

没有更多推荐了,返回首页