美文网首页
3DTouch 组件化之路

3DTouch 组件化之路

作者: 算命的李老师 | 来源:发表于2018-11-23 11:47 被阅读0次

起因:项目需要,因为发现竞品公司已经有3D touch 的应用,于是写了这么一套东西。

组件化一直在做,挑了一个最近刚刚发布的热乎的组件 3DTouch 组件

不上代码都是耍流氓 上链接 ---> LG3DTouch

集成方式
pod 'LG3DTouch'

组件是怎么弄出来怎么发布的这篇就不细说了

看货

@interface LG3DTouchManager : NSObject

+ (instancetype)shareManager;

#pragma mark - 图标事件
/**
 注册元素 自动完成覆盖 使其一定能被注册

 @param shortcutItem 元素
 */
- (void)autoRegisterUnit:(LGShortcutItem *)shortcutItem;

/**
 移除所有item元素
 */
- (void)reset;

/**
 删除最近的一个元素
 */
- (void)removeNearlyItem;

#pragma mark - 预览事件

/**
 注册预览事件

 @param target 预览需要的模型
 */
- (void)registerPreviewController:(LG3DTouchProxyTarget *)target
                      paramBlock:(void (^)(UIViewController *previewController,UIView *sourceView))block;



/**
 注册预览状态下的按钮

 @param title <#title description#>
 @param style <#style description#>
 @param handler <#handler description#>
 @return <#return value description#>
 */
- (UIPreviewAction *)registerActionWithTitle:(NSString *)title style:(UIPreviewActionStyle)style handler:(void(^)(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController))handler;


@end

初始化是普通单例 后续改进的话可能避免使用单例,或避免单例持久化,毕竟我们在使用app的过程中,很少用到3D Touch 可以说几乎不用。没必要将这个单例持久化。

一共有这么几种调用体

一、app icon的按压事件

按压弹出的是一个列表,列表就需要元素。
我这里用这种方式添加元素
- (void)autoRegisterUnit:(LGShortcutItem *)shortcutItem;
目的是为了增强封装性,就别找系统的UIApplicationShortcutItem了,费劲。

LGShortcutItem中封装了url这个属性

@interface LGShortcutItem : NSObject

@property (nonatomic, strong) NSString *typeName;

@property (nonatomic, strong) NSString *localizedTitle;

@property (nonatomic, strong) NSString *localizedSubtitle;

@property (nonatomic, strong) UIApplicationShortcutIcon *icon;

/**
 遵循跳转协议
 */
@property (nonatomic, strong) NSString *url;

这个url属性在UIApplicationShortcutItemuserInfo属性里,直接用糖衣语法,获取方式为userInfo[@"url"]

元素的初始化方法也准备了

- (instancetype)initWithIconType:(UIApplicationShortcutIconType)iconType
                        typeName:(NSString *)typeName
                  localizedTitle:(nonnull NSString *)localizedTitle
               localizedSubtitle:(nullable NSString *)localizedSubtitle
                         jumpUrl:(NSString *)url;

- (instancetype)initWithIconName:(NSString *)iconName
                        typeName:(NSString *)typeName
                  localizedTitle:(nonnull NSString *)localizedTitle
               localizedSubtitle:(nullable NSString *)localizedSubtitle
                         jumpUrl:(NSString *)url;

就这样,通过
- (void)autoRegisterUnit:(LGShortcutItem *)shortcutItem;成功注册了一个图标。

核心代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    
    LGShortcutItem *item1 = [[LGShortcutItem alloc] initWithIconType:UIApplicationShortcutIconTypeHome typeName:@"GoType1" localizedTitle:@"去目的地1" localizedSubtitle:nil jumpUrl:@"action://page=home"];
    
    LGShortcutItem *item2 = [[LGShortcutItem alloc] initWithIconType:UIApplicationShortcutIconTypeTask typeName:@"GoType2" localizedTitle:@"去目的地2" localizedSubtitle:@"子标题2" jumpUrl:nil];
    
    [[LG3DTouchManager shareManager] autoRegisterUnit:item1];
    [[LG3DTouchManager shareManager] autoRegisterUnit:item2];
    
    return YES;
}

通过实验发现 iPhone 3D Touch 最多只能展示4个元素。
那么就有这种情况:我在appDelegatedidFinishLaunchingWithOptions添加了三个元素,但是四个元素需要通过业务逻辑才能确定,比如 某滴打车,你需要填写了家和公司两个地址才会在按压图标的时候有另外两个元素添加进去。
所以在代码实现上,添加了一个操作

- (void)autoRegisterUnit:(LGShortcutItem *)shortcutItem {
    
    [self unlock];
    [self registerUnit:shortcutItem];
    if (self.shortcutItems.count > 4) {
        [self removeNearlyItem];//在已经大于4个的情况下添加元素失败,删除最上层的元素,再注册新元素到最上层,添加成功
        [self autoRegisterUnit:shortcutItem];
    }
    [self lock];
}

很好奇 lock 和 unlock内是什么蜜汁操作?
我的想法很简单,就是将本地的元素列表和UIApplication内存储同步,上代码

- (void)lock {
#if DEBUG
    NSAssert(self.shortcutItems.count, @"self.shortcutItems 不可用为空数组");
    NSAssert(self.shortcutItems.count <= 4, @"LG3DTouchManager 最多允许添加4个元素 可以使用autoRegisterUnit:方法来自动覆盖");
#endif
    //只有调用了 lock 方法 3DTouch元素才会生效
    [UIApplication sharedApplication].shortcutItems = self.shortcutItems;
    _isLock = YES;
}

- (void)unlock {
    self.shortcutItems = (NSMutableArray *)[UIApplication sharedApplication].shortcutItems;
    _isLock = NO;
}

蜜汁lock·····
本意是打算防止在项目中任意地方随意添加删除元素,写着写着觉得还是组件内写好算了。

元素点击的回调

- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
   //只要是点击item 进来的,就会走这里,不论程序是在后台还是新启动   
  NSString *url = shortcutItem.userInfo[@"url"];
  if(url.length) {
        NSLog(url);//输出跳转地址 这里url 可以根据自定义的跳转协议来跳到指定页面。内容可以参考http的get请求方式传递参数
      }
}
二、tableViewCell 的按压事件

其实整个流程都比较简单 在cellForRowAtIndexPath内调用
直接上代码


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *str = [NSString stringWithFormat:@"%@",[indexPath.row]];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reusedId];

    cell.contentView.backgroundColor = [UIColor whiteColor];
    cell.textLabel.text = str;
    
    //注册预览页和当前页
    LG3DTouchProxyTarget *target = [[LG3DTouchProxyTarget alloc] initWithPreview:@"LGPresentationViewController" current:self sourceView:cell];
    [[LG3DTouchManager shareManager] registerPreviewController:target paramBlock:^(UIViewController *previewController,UIView *sourceView) {
        //在这里传递参数
        LGPresentationViewController *vc = (LGPresentationViewController *)previewController;
        UITableViewCell *returnCell = (UITableViewCell *)sourceView;
        vc.strInfo = returnCell.textLabel.text;
    }];
    
    return cell;
}

这里需要用 LG3DTouchProxyTarget包装一下
这个操作是不是有点熟悉,和消息转发机制里的
NSInvocation重新包装方法的样子差不多
这个方式还可以用于NSTimer 里的解除强引用。

目的是为了让单例不直接持有self,这样就可以避免强引用。

然后呢?

没有了。

是不是以为要接代理之类的,并没有。一切乱七八糟的注册和判断和预览界面的初始化都在组件里完成了,是不是很方便。
只要实现了这个方法,预览页,当前页,当前控件就 高聚和低耦合的方式连接在了一起。

注:为了避免重复创建预览页的实例,只需要传递预览页的类名字就可以了。NSString形式,划重点。

- (id)initWithPreview:(NSString *)previewControllerName current:(UIViewController *)current sourceView:(UIView *)sourceView;

那么有的界面可能需要传递参数才能展示内容,参数怎么传递呢
在这里

[[LG3DTouchManager shareManager] registerPreviewController:target paramBlock:^(UIViewController *previewController,UIView *sourceView) {
        //在这里传递参数
        LGPresentationViewController *vc = (LGPresentationViewController *)previewController;
        UITableViewCell *returnCell = (UITableViewCell *)sourceView;
        vc.strInfo = returnCell.textLabel.text;
    }];

组件返回了一个预览页的实例,和按压控件的实例。

现在核心功能实现完毕。

附一张第一次提交cocoaPods成功的截图。

image

相关文章

  • 3DTouch 组件化之路

    起因:项目需要,因为发现竞品公司已经有3D touch 的应用,于是写了这么一套东西。 组件化一直在做,挑了一个最...

  • iOS组件化文章汇总

    iOS应用架构谈 组件化方案 APP组件化之路 我所理解的组件化之路 iOS 组件化方案探索 围观神仙打架,反革命...

  • 学习笔记 - iOS 组件化方案

    一、蘑菇街 App 的组件化之路 二、iOS应用架构谈 组件化方案 三、蘑菇街 App 的组件化之路·续 四、iO...

  • iOS 组件化

    参考:蘑菇街 App 的组件化之路蘑菇街 App 的组件化之路·续 iOS应用架构谈 组件化方案在现有工程中实施基...

  • 路由组件化

    撸一个简单路由RouteriOS 组件化与路由的本质App 的组件化之路

  • 想变老司机的,请上车

    由于本人水平有限,先以转载的两篇好文章开篇: 蘑菇街 App 的组件化之路 蘑菇街 App 的组件化之路·续

  • iOS开发之组件开发

    预读 iOS组件化思路-大神博客研读和思考iOS的组件化之路(从理解到应用)

  • iOS组件化之路总结二(github发布CocoaPods支持的

    前言 接上一篇文章:iOS组件化之路总结一(CocoaPods安装三方库原理)继续iOS组件化之路,记录一下如何发...

  • iOS 组件化

    豆瓣App的模块化实践 手机天猫解耦之路 蘑菇街 App 的组件化之路 京东iOS客户端组件管理实践 谈谈我的理解...

  • iOS组件化开发index

    01 iOS 组件化 —— 路由设计思路分析--冰霜02 蘑菇街 App 的组件化之路--Limboy03 蘑菇街...

网友评论

      本文标题:3DTouch 组件化之路

      本文链接:https://www.haomeiwen.com/subject/kbfjqqtx.html