iOS - 第三下输入法App原理调研、App Group数据共享(下)

简介: 本文Demo同步Github

2.3 键盘UI布局


我把源码上传到了Github


CCInput


键盘的UI布局我以简单以搜狗输入法的数字键盘为例,这里附上代码说明,具体请查看Demo代码


KeyboardViewController 创建keyboard extension时,系统自动创建的vc,继承自UIInputViewController,键盘的布局、逻辑处理都在此类中


CCLeftTableView 左侧符号输入,是一个TabView,,支持增加符号数据源

CCCenterView 中间数字键盘及底部切换、数字0、空格功能


CCRightView 右侧删除、句号、@符号、换行功能


CCKeyboardModel 键盘数据源Model,Model有两个属性,分别是

NSString *string 用于键盘按钮文本的展示


CCKeyboardAction keyboardAction 是点击事件的枚举类型,点击键盘的时候通过此属性统一处理


简单的写了个通过runtime自动获取属性解析json为model的方法


主要是UI和数据结构,此处不深入探究,感兴趣请看demo,此处有个自定义键盘高度的坑注意下:


  1. 通过简单的setframe无法更改键盘默认高度


  1. 需要通过设置NSLayoutConstraint的方式,切在viewDidLoad方法中设置无效


  1. 需在viewDidAppear之前设置键盘高度


这个问题的解决方案因为国内做键盘的公司比较少,百度搜索不到相关资料,附上stackoverflow链接


stackoverflow: iOS 8 Custom Keyboard: Changing the Height


Demo效果:


image.png

https://upload-images.jianshu.io/upload_images/1903571-a3874c99894ea210.image?imageMogr2/auto-orient/strip|imageView2/2/w/421/format/webp

Demo效果.gif


同时附上Demo中代码

static CGFloat KEYBOARDHEIGHT = 256;
@interface KeyboardViewController ()
<CCTopBarDelegate,
CCLeftViewDelegate,
CCCenterViewDelegate,
CCRightViewDelegate>
/// 用于设置键盘自定义高度
@property (nonatomic, assign) NSLayoutConstraint *heightConstraint;
@end
@implementation KeyboardViewController
- (void)prepareHeightConstraint {
    if (self.heightConstraint == nil) {
        UILabel *dummyView = [[UILabel alloc] initWithFrame:CGRectZero];
        dummyView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:dummyView];
        self.heightConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:KEYBOARDHEIGHT];
        self.heightConstraint.priority = 750;
        [self.view addConstraint:self.heightConstraint];
    } else {
        self.heightConstraint.constant = KEYBOARDHEIGHT;
    }
}
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self prepareHeightConstraint];
}
/// 重写的父类方法,苹果建议在此处updateViewConstraints
- (void)updateViewConstraints {
    [super updateViewConstraints];
    if (self.view.frame.size.width == 0 && self.view.frame.size.height == 0) {
        return;
    }
    [self prepareHeightConstraint];
}


UIInputViewController 涉及到的方法说明:


  • advanceToNextInputMode 切换到下一个输入法


  • dismissKeyboard 退出键盘(相当于resignFirstResponder


  • insertText 插入文本(尾部)


  • deleteBackward 删除输入框内上一个文本


3. 输入法类App原理


3.1 主程序与键盘拓展的关系


image.png


图源自网络


第三方输入法,分为主程序(containing App)、键盘(extension), 分别对应Demo中的InputAppCustomKeyboard, 主程序在桌面可见,Host App则是使用输入法的其它App,


  • 主程序和键盘Extension正常情况是无法共享数据的(沙箱隔离)
  • 在开启完全访问时,主程序和键盘Extension可以共享数据(通过app groups)
  • 主程序和Host App无法共享数据(沙箱隔离)
  • 键盘Extension和Host App只能共享文本数据(通过系统UITextDocumentProxy)


3.2 完全访问


在设置-通用-键盘中,苹果有对完全访问做说明,摘录如下


第三方键盘提供了另一种途径来键入键盘数据。这些键盘可以访问您键入的所有数据,包括银行账户、信用卡号码、街道地址及其他个人信息与敏感信息。这些键盘还可能访问相邻文本及数据,这些信息对改进自动更正功能卓有帮助。


如果您启用“完全访问”,开发者即获得许可访问、收集与传输您键入的数据。此外,如果附带键盘的第三方应用程序获得您的许可访问地理位置信息、照片、或其他个人数据,那么此键盘也可收集并将该信息传输至键盘开发者的服务器上。如果您停用某第三方键盘的“完全访问”,之后再重新启用,那么键盘开发者则可能能够访问、收集并传输网络访问禁用期间所键入的信息。


如果您不启用“完全访问”,那么开发者则不可收集与传输您键入的数据。未经您许可,任何未授权的数据收集或传输行为均违反其开发者协议。此外,技术限制同样在防止未经许可的访问方面起作用。任何试图破坏此类限制的尝试同样违反开发者协议。


你任何时候均可选择停用第三方键盘。打开“设置”,轻点“键盘”,将该键盘从键盘列表中移除即可。


如果您使用第三方键盘,即需遵守键盘开发者的条款、隐私政策及做法。使用此类键盘App与服务之前,您应仔细阅读其条款、隐私政策和做法,以了解他们如何使用您的数据及其他信息。


总结就是,只有开启了完全访问,输入法App才能:


  • 访问、收集、传输输入的数据
  • 访问并上传位置、照片、个人数据(通讯录之类权限隐私数据)
  • 如果开启之后又关闭,那么开发者还是能够传输禁用期间的数据
  • 如果不开启,那么因为苹果的技术限制(沙箱),开发者并不能上传键盘Extension获取到的数据


3.3 App Groups数据共享


官方文档:Sharing Data with Your Containing App


image.png

app_extensions_container_restrictions_2x.png


简单来说,开启了app groups,相当于生成一个中间数据共享区(shared container)来将App's containerExtension's container的数据关联并共享


通过以下方式就可以共享数据

// Create and share access to an NSUserDefaults object
NSUserDefaults *mySharedDefaults = [[NSUserDefaults alloc] initWithSuiteName: @"com.example.domain.MyShareExtension"];
// Use the shared user defaults object to update the user's account
[mySharedDefaults setObject:theAccountName forKey:@"lastAccountName"];


4 输入法App和逆向(个人瞎猜,可能鲁迅人本身根本没这么想)


通过上文3.13.23.3我们知道, 主App和Extension之间要想共享数据,必须开启完全访问通过App Groups的方式共享数据,对于一款键盘类App,他肯定是希望App和Extension能实现数据共享,以达到以下需求:


  • 实时更新网络高频热词,用于联想输入
  • 共享键盘皮肤
  • 存储用户高频输入的词汇、通讯录等数据,上传服务端,当用户换设备时,能同步并共享给新设备的Extension


但是由于沙箱的限制,如果用户没有开启完全访问,以上三点需求就达不成了。事实上以上三点需求对我这样的用户来说非常重要,无缝衔接切换设备的快感是无法形容的,比如当我在iPhone上输入ma后,我选择了联想词汇表中的码代码的小马,然后当我在mac上使用搜狗输入法同样输入ma,mac也联想到了码代码的小马,这样会将我的输入效率提高很多


此时就用到了逆向技术


苹果有沙箱隔离,逆向里有沙箱逃脱(沙箱逃脱详细解释请参考我之前文章沙箱逃脱)

沙箱逃脱简单来说就是跨进程访问数据共享数据,放在这里就是,即使用户不开启完全访问,主App也能访问Extension的数据,以实现如上三点需求。


只是目前沙箱逃脱技术只能在越狱设备实现,也许未来某一天某个大牛实现了在未越狱设备的沙箱逃脱,那对于逆向开发者来说,简直是这盛世如你所愿,大好河山任你看...


相关文章
|
6月前
|
监控 安全 数据可视化
java基于微服务的智慧工地管理云平台SaaS源码 数据大屏端 APP移动端
围绕施工现场人、机、料、法、环、各个环节,“智慧工地”将传统建筑施工与大数据物联网无缝结合集成多个智慧应用子系统,施工数据云端整合分析,提供专业、先进、安全的智慧工地解决方案。
157 1
|
6月前
|
JSON JavaScript 安全
iOS应用程序数据保护:如何保护iOS应用程序中的图片、资源和敏感数据
iOS应用程序数据保护:如何保护iOS应用程序中的图片、资源和敏感数据
59 1
|
6月前
|
传感器 人工智能 监控
Uni-app智慧工地数据大屏可视化监管平台源码带APP
智慧工地的核心是数字化,它通过传感器、监控设备、智能终端等技术手段,实现对工地各个环节的实时数据采集和传输,如环境温度、湿度、噪音等数据信息,将数据汇集到云端进行处理和分析,生成各种报表、图表和预警信息,帮助管理人员了解工地的实时状况,及时做出决策和调整,
173 0
|
6月前
|
存储 JavaScript 小程序
jQuery、vue、小程序、uni-app中的本地存储数据和接受数据是什么?
jQuery、vue、小程序、uni-app中的本地存储数据和接受数据是什么?
74 0
|
6月前
|
存储 运维 安全
iOS加固原理与常见措施:保护移动应用程序安全的利器
iOS加固原理与常见措施:保护移动应用程序安全的利器
90 0
|
6月前
|
Android开发 移动开发 小程序
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
|
1月前
|
JSON API 网络安全
App数据的爬取
App数据的爬取
|
3月前
|
存储 SQL JSON
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
|
3月前
|
缓存
【Azure Function】Function App代码中使用Managed Identity认证获取Blob数据时遇见400报错
【Azure Function】Function App代码中使用Managed Identity认证获取Blob数据时遇见400报错
【Azure Function】Function App代码中使用Managed Identity认证获取Blob数据时遇见400报错
|
3月前
|
iOS开发 开发者
iOS平台RTMP|RTSP播放器如何实时回调YUV数据
我们在做RTMP、RTSP播放器的时候,有开发者需要自己处理拉取到的YUV数据,做二次分析之用,为此,我们做了以下的设计:InitPlayer之后,再调用SmartPlayerStart()接口之前,设置yuv数据回调即可。