- 原文地址:Exploring Apps Without Jailbreaking
- 原文做者:
- 译文出自:掘金翻译计划
- 本文永久连接:github.com/xitu/gold-m…
- 译者:melon8
- 校对者:ALVINYEH
Medium 的 iOS应用是一个带伪导航条的原生应用,而 Product Hunt 则是用 React Native 构建的。前端
Medium iOS 应用(左)和 Product Hunt iOS 应用(右)。android
我是怎么知道的呢?除了我本身编写代码或向开发人员询问之外,我能够用几个简单的测试来肯定 —— 不须要越狱。ios
想知道我怎么作的?git
在网络的“早期”时代,很容易了解任何网站是如何创建的。经过在浏览器中查看源码,底层代码能够暴露给任何人看到、拿去混淆或者重用。随着网络的发展和框架的使用,网站变的愈来愈复杂,到如今,这几乎是不可能作到的。github
使用 Chrome 检查 Medium 文章的 HTML。web
App 有相同的问题,但更糟。app 会通过编译,这意味着原代码已经从人类可阅读的格式转换为计算机友好格式。面试
虽然有工具能够反编译 iOS 应用,但它们须要越狱设备,特殊工具和专业编程知识。我将分享一些不须要任何黑客技巧的策略 —— 只要应用安装在你的设备上就够了。编程
咱们的策略很简单:将应用推向极限,期待着出情况。若是咱们能看到它们出现的具体问题,就能够推断它们如何工做。后端
咱们将尝试回答如下问题:浏览器
为了收集数据,咱们将作五个测试。我将解释每项测试如何执行,寻找的目标是什么以及从结果中能够得出什么结论。
咱们将测试:
一个按钮看起来很简单。你点击它,而后发生一些事情。可是,并不是全部的按钮都是相同的。
咱们将测试按钮交互的边缘状况 —— 用户不只仅是点击一下按钮时的行为。
iOS 开发新人经常对 UIButton
(iOS 上的默认按钮组件)的交互复杂性感到惊讶。在交互中的不一样节点有九个事件会发生。
touchDown
touchDownRepeat
touchDragInside
touchDragOutside
touchDragEnter
touchDragExit
touchUpInside
touchUpOutside
touchCancel
(在苹果开发者文档中了解有关 UIControlEvents
的更多信息。)
几乎全部的按钮都会在 touchUpInside
上执行一个动做(当用户在控件边界内触摸并松手时)。用户触摸时,大多数按钮都会表现出特殊的状态。
真正的区别因素是按钮如何处理 touchDragExit
和 touchDragEnter
事件。当用户触摸按钮时,按钮如何响应,而后不抬起手指,拖动到按钮以外,而后再拖回来。
在 iOS 模拟器中测试标准按钮。
标准的 UIButton
有一些常见的行为:
可是,自定义的原生按钮一般会丢掉这些默认动画。
没有动画的自定义按钮。
咱们来看看 Medium 应用。若是你在 Medium 的 iOS 应用中阅读此内容,你能够直接在上面试试!
让咱们试一下右下角的这个看起来很花哨的按钮:
若是你点击按钮,而后按住不动,将手指向外移动并返回,你会发现手形图标在其明暗状态之间切换。
(个人下一篇文章:“我如何经过增加黑客来获得 10 万用户” 😉)
React Native 按钮很容易认出来。它们一般有一个缓慢的淡入淡出动画,而且适用于一切 React Native 按钮。
Facebook 的 F8 应用中的按钮动画。这是 React Native 应用程序中的常见效果。
React Native 应用程序一般会大量使用滚动视图,这会使按钮的行为难以测试,由于拖动按钮也会滚动视图。
当谈到 React Native 的话题时,另外一个泄露秘密的表现就是 cell 的点击状态。iOS 的原生 cell 点击后会出现一个纯色背景,而 React Native 的 cell 点击后与其按钮相似的高光效果。
左:React Native cell 行为。右:原生 cell 行为。
在我下载测试的 PhoneGap 应用程序中,约 95% 的按钮彻底没有触摸状态,其他的约 5% 保留了触摸按钮的状态,但在拖出或返回时没有任何表现。
请记住很重要的一点,这些按钮行为很容易被重写。表现出特定的行为并不意味着一个绝对的缘由 —— 它只是某个方向的线索。
可是随着时间的推移,你会不自觉对按钮有一种“感受”,但它是探索 app 如何构建的,作出有根据猜想的最简单方法之一。(这种技术也能够用来肯定一个交互元素是一个按钮仍是其余类型的控件。)
从 iOS 7 开始,用户能够经过滑动显示屏的左侧边缘来导航到前一个界面。这个手势特别有趣,由于它是交互式的,这意味着它能够搓来搓去。
在 iOS 上使用标准的 UINavigationController
时,这种行为是自带的。出于某种缘由,许多应用程序弃用了标准导航栏,并最终致使了导航转换效果的丢失,损坏或质量不高。
让咱们在 Medium 中试一下。
比较 Medium(左侧)和 App Store(右侧)上的导航转换效果。
与标准导航转换不一样,Medium app 将导航栏与屏幕的其他部分一块儿移动。而标准状况下,导航栏保持不变,上面的全部标签会淡入淡出。
另外,Medium app 的前一个界面上的黑色半透明叠加层较暗,看起来导航转换部分被重写了,或者更有多是直接使用了自定义的组件。
我我的认为它看起来很是好,而且理解他们出于设计和开发的须要而采起了这种方法。
从开发的角度来看,React Native 中的导航功能实现起来更加困难。所以,React Native 应用程序倾向于使用自定义导航转换,而不是使用UINavigationController
的标准“push”和“pop”。
Facebook 的 F8 应用程序中的自定义转换效果。
iOS 上的默认模态演示不是交互式的,而且在从新出现的界面上没有缩放效果。
如下是 React Native 中自定义转换的另外一个示例。
Facebook 的 F8 应用中的导航转换效果。
没有阴影或黑色叠加,但真正泄露秘密的表现是动画时机。在这个 gif 中很难看到,可是在我抬手以后,动画完成比日常慢得多。
就像按钮触摸状态同样,经过测试许多导航转换,你能够在一段时间的后得到一种“感受”。
这是我最喜欢的测试之一,由于它能够揭示更多关于 app 的信息,而不只仅是导航栏的工做方式。若是手势把 app 搞出了 bug,则可能获得的信息不只仅是导航转换的方式了。
可是,就像按钮触摸状态同样,导航转换能够被重写。然而实际上,因为导航转换须要大量的开发工做,因此导航转换不太可能被严格定制。
你想要超能力?试试 VoiceOver。
VoiceOver 是 Apple 版本的屏幕阅读器。适用于视力障碍用户,这种辅助功能选项会大声朗读用户界面。
VoiceOver 有另外一个咱们更感兴趣的效果:它在当前选定的元素周围显示一个黑框。
在 App Store 和 Weather 应用程序中选择元素的声音。
这使咱们可以将界面分解成各个部分。不须要猜想界面是如何构建的,咱们可让 VoiceOver 告诉咱们!有时它甚至会大声朗读元素的类型(“按钮”,“日期选择器”等)。
若是您之前没有使用过 VoiceOver,那么它很值得去学习。基本概念:
让咱们来研究一下在 Medium 中使用 VoiceOver 的效果。
使用 VoiceOver 在 Medium 中选择帖子的标题。
大多数元素的表现和预期一致。VoiceOver 只是读取选择的内容或元素的名称。可是,有一些不寻常的行为。
在主屏幕上,选择帖子的标题只能读取标题的一半。首先它说,“Color Contrast Crash C”,而后选择标题的底部读取“Course for Interface Design”。这说明 label 的布局确定有一些自定义的部分,这使得 VoiceOver 认为标题被分红多个 label,每行一个 label。(个人猜想是他们为自定义行间距的 label 构建了一个变通方案,而一般的解决方案是使用 attributedString
属性,而且他们的方案可能会致使之后出现复杂问题。)
选择描述 label 后,咱们能够看到 VoiceOver 揭示隐藏信息的威力。对于大多数用户来讲,label 只是显示“估计有 2.85 亿...”。可是VoiceOver告诉咱们更多的信息:“估计有 2.85 亿人视力受损。这个数字包括从法律上来看这些人的人数“。在这种状况下说明,全部数据都存储在标签中,但视觉上被截断了。
Medium 的 VoiceOver 演示。(确保你的声音不是静音)
若是幸运的话,你可使用它来访问你没法访问的信息。
这是另外一个有趣实验。在“书签”选项卡上,若是你没有书签,则有一个不可见的标签。它说:“要给文章加书签,在任一地方点击书签图标,文章会被添加到这个列表。”
使用 VoiceOver 在 Medium 中选择不可见标签。
我猜是开发人员会快速暂时隐藏这个标签,并假定可能未来产品又会让它显示。(或者,也许我正在被 A/B 测试。)
VoiceOver 也适用于基于网络视图的 app。若是你听到“连接”或“标题级别”等字眼时,表示你正在一个网络视图之中。
此外,文本元素可能会基于样式以各类奇怪的方式拆分(由于它的 HTML 表示),而且元素可能不会天然分组。
游戏(由 Unity,SpriteKit 等构建)一般根本没有任何 VoiceOver 支持。
VoiceOver 提供的证据在这些测试中最可靠。它显示元素的可视范围,并能够读取不可见的属性。这是关于任何界面的宝贵资料。
随着你更多地使用 VoiceOver,你会学习到各类 UI 元素的默认表达方式,并开始注意到它的不一样之处。
与上述任何测试同样,VoiceOver 不是 100% 可靠的。全部的 VoiceOver 文本和边界框均可以由开发人员配置。针对 VoiceOver 优化过的应用程序也可能会揭露更少关于应用程序如何工做的信息,由于开发人员会修复可能致使 app 出问题的 bug。
(专业提示:将 VoiceOver 设置为你的“辅助功能快捷键”,便于在测试时打开和关闭。)
与 VoiceOver 相似,动态类型 是适用于视力障碍用户的辅助功能。它能够修改整个系统的文字大小。
咱们想要使用动态类型来破坏布局。有了新的“辅助功能中的更大字体”后,这比以往更容易看出 app 端倪,这绝对是巨大字体。
调至最大字体的“更大文本”设置界面。
动态类型 能够在设置 > 辅助功能 > 更大字体中设置。这也能够做为一个 widget 添加到 iOS 11 中的控制中心,以便于访问。
不幸的是,Medium 不支持 动态类型,因此咱们将使用 App Store 演示。
我将文字大小设置为最大值,并找到了一个错误的布局 —— 搜索界面上的一个广告。
最大字体(左侧)和默认字体(右侧)的 App Store 搜索界面。
文本“22K”布局的很是好,但它没有揭露太多布局的秘密,由于布局为更大字体作了调整(能够看到元素改位堆叠排列,而不是并排)。
我最喜欢的部分是淡蓝色的“广告”按钮。和正常字体大小时的漂亮的圆角矩形不一样,咱们获得了一个怪怪的拉伸的形状。
更大字体设置下的“广告”按钮。
个人猜想是,这个蓝色框被绘制成一个硬编码半径的自定义路径。一般,控件不会使用动态类型调整大小(请参阅“GET”按钮做为示例),因此这里有一些自定义内容。
####动态类型的结论
有些应用程序根本不支持 动态类型。即便支持,他们也可能不支持辅助设置中更大的字体。
可是当动态类型生效时,就能够对布局进行压力测试。使用 VoiceOver 已经能够了解一些信息,结合动态类型更有助于验证理论。一般支持动态类型的 app 也会测试这一部分,这会减小显示有用信息的机会。
另外一个简单的测试是启用飞行模式。飞行模式会禁用 Wi-Fi 和蜂窝移动网络,这会当即致使网络请求失败。经过在各类状况下禁用网络链接,咱们能够看到 app 如何出问题。
在 Medium 中,若是你加载主页,打开飞行模式,并选择一篇文章,文章仍会加载。事实上,整个帖子仍然可读。
飞行模式下的 Medium。文字内容加载,但图像不加载。
由此,咱们推断 Medium 在加载预览时会拉取整个帖子的内容(并进行一些缓存)。
App Store 也会延迟加载图像。加载完一个页面并滚动到底部以后打开飞行模式会看到图像区域是空白的。
App Store 在飞行模式下。图像(即便在同一页面上)彷佛是懒加载。
大多数现代应用程序重度依赖于网络链接,来下载内容而后容许交互,因此飞行模式会让大多数 app 出错。
在我测试过的 React Native app 中,大多数应用程序经过删除屏幕上的全部内容,并显示一条自定义的“无链接”消息,对缺少互联网链接的状况当即作出反应。
对于基于 webview 的 app,大多数没有反应。没有迹象代表当前正在加载或者加载失败。
不幸的是,飞行模式并无给出如何构建应用程序的明确答案,由于大多数应用程序在没有可用链接时会有某种回退方式。
想继续深刻?经过观察 app 的网络流量,你能够了解更多关于其余应用的信息。Charles Proxy(代理)的 iOS app 是洞悉各类 app 的好方法,但须要一些 HTTP 网络知识。
尽管可能不能彻底肯定 app 的构建方式,但有一些方法可让你进行有根据的猜想。经过研究边缘案例,咱们能够更大程度上揭示它们的内部运做。
咱们的学习也能够为咱们本身的 app 的设计和开发提供信息。多了解一些方法有助于咱们在将来作出更好的决策。
在一个不开源的应用程序的世界中,作些小改动的能力有限。(或从新发现)思考事物运转的方式的乐趣。
喜欢这个故事?在 Medium 上留言,并与 iOS 设计/开发者朋友分享。想要了解最新的移动应用设计/开发?在 Twitter上关注我:twitter.com/nathangitte…
感谢 David Okun 修改本文的草稿。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。