创建iOS应用程序需要哪些技能?Yandex报告

移动开发人员需要具备一套清晰的技能。您需要在创建和发布应用程序期间出现的特定任务的上下文中讨论它们。Arthur Antonov在Yandex机器翻译部门担任iOS开发人员。在针对学生和初学者的报告中,Arthur解释了开发人员创建现代移动软件必须具备的能力。


-我们部门有两个移动应用程序:Yandex.Translate和Yandex.Keyboard。在Translator中,我们拥有许多复杂的技术,例如语音输入,通过照片识别文本,使用神经网络进行文本翻译。另一个挑战是离线维护此功能。也就是说,即使没有Internet,此功能也将为您工作。



键盘是一类单独的应用程序;对其速度和应用程序本身的质量有不同的要求。俄语自动更正对我们有用:它可以帮助用户,但不会打扰他。语音输入,滑动输入。





动态网格是另一个很酷的功能:它试图预测下一个字母,并据此更改标签。也就是说,更容易找到一封可能的信。



在学校,我从事体育节目制作。但是,当我进入大学时,在我看来这有点无聊,我想为普通人开发程序,并且希望它们随时随地都可以使用。因此,我决定选择移动开发。但是移动应用程序是多方面的,在我之前出现的最大问题是从哪里开始。

现在,互联网上到处都是在线课程,教程,各种主题的书籍,而且脑袋爆炸了。目前尚不清楚从哪里开始。因此,在我的报告中,我想帮助您建立成为移动开发人员的学习道路。一开始值得研究的东西,可以推迟的研究。



在分析了我几年的工作后,我确定了解决大多数问题所必需的几个关键技能。这些是基本技能和所谓的工具箱技能。开发移动应用程序时不需要它们,但是如果您拥有它们,那么您的生活将变得更加轻松,并且应用程序的质量将大大提高。

由于没有实践的理论已经一去不复返了,我们将以Yandex.Translator的简化版本为例学习技能。完成项目后,您只会看到白屏。

让我们使用UI恢复我们的应用程序。





创建界面有两种经典方法-图形编辑器和代码。这是他们在移动开发中的好莱坞主题之一。图形编辑器中有开发人员,除了代码以外,其他人什么也看不到。但我建议您尝试两种方法。您一定会碰到它们,此外,没有人会禁止您组合各种方法,例如,在图形编辑器中执行的简单操作以及在代码中已经存在的复杂操作。



最近,iOS开发人员有了一个新的SwiftUI框架,试图将这两种方法结合起来。也就是说,在图形编辑器中进行更改时,您的代码也会更改,反之亦然。也许当这个框架广泛传播时,所有争执都会被遗忘。

不幸的是,SwiftUI仅从iOS 13开始可用,因此到目前为止,它尚不能在大型项目中使用。



图形编辑器具有非常简单的界面。我们采用现成的组件,将它们拖动到虚拟屏幕上,然后立即查看我们得到了什么。因此,创建简单的UI组件非常快。我们还可以为不同设备调整虚拟屏幕的大小,并在不启动应用程序的情况下测试我们的界面。





另一方面,我们在代码中有一个界面设计。在代码中开发接口时,UIKit库会派上用场,并且您将使用其中的小构建基块UIView。 UIView对象大致对应于您在屏幕上显示的组件。就像在图形编辑器中一样,您具有常用组件(例如按钮和文本)的现成子类。

使用代码进行开发时,了解其他UIView可以在其内部创建UIView非常重要,也就是说,您可以构建任何复杂的接口。结果,您得到了所谓的树。从代码进行修改更容易。也就是说,如果您有一个非常动态的用户界面,那么可能值得用代码编写它,以后您将更容易对其进行修改。



让我们看看可以为我们的翻译器编写什么代码。

首先,我们将背景色设置为黄色。然后,我们在用户输入英文文本的地方添加一个输入字段。接下来,我们添加一个用于分隔符的分隔符,最后添加一个输出字段,同时禁止用户对其进行编辑。

我们已经准备好用户界面,但是该应用程序仍然没有用。它不能解决用户的主要任务-文本翻译。

让我们添加此功能。 SDK平台的功能将为我们提供帮助。



平台SDK是一组用于创建移动应用程序的工具和库,这些工具和库由Apple以及相应地由Google提供给我们。

目前,SDK具有许多与操作系统进行交互的低级库,并且您可以轻松实现几乎任何想法的移动应用程序。

您将使用哪种库取决于您的应用程序的具体情况。例如,如果我们要制造相机,则很可能需要两个库:用于相机使用的AVFoundation库和用于图像处理的CoreImage库。

因此,在此阶段不必记住所有库,这是完全不可能的。更重要的是找到正确工具的能力。不幸的是,官方文档并不总是完整地记录功能。有时,您会在博客或其他开发人员的Twitter上找到一些有趣的东西。值得关注的信息领域。

那么,我们需要SDK的翻译服务吗?



我们的翻译器是经典的客户端-服务器应用程序:我们向服务器发出请求并获得响应。然后,我们以某种方式对其进行转换并将其显示给用户。基金会框架将帮助我们完成这项任务。它包含用于解决日常任务的便捷抽象。

我们将从中获取URLSession类,这是用于使用http协议与服务器一起工作的类,以及JSONSerialization,这是帮助我们从JSON格式转换对象的类。



因此,让我们看看我们需要为该功能编写哪些代码。左侧是每次更改用户输入时都会执行的方法。我们首先使用翻译服务器的地址创建一个URL,然后进行请求。此外,在收到答案后,我们将从JSON格式解析它,然后从中获得所需的文本,即翻译文本。最后一步-我们说,您需要在输入字段中设置收到的答案。

让我们看看我们得到了什么。用户输入hello,然后出现“ hello”:



但是“ hello”以某种方式出现了很长一段时间,似乎没有出现网络延迟。为了提高可靠性,让我们与哥哥进行比较:

打开GIF

在这两个应用程序中,我们输入文本hello,然后看到翻译已经在真正的翻译器上出现了好几次了。在我们的翻译器上,翻译的内容很大。

要解决此问题,我们需要熟悉移动应用程序中的多线程模型。



就像台式机一样,移动应用程序也运行在多线程环境中。但是有一个重要的限制。移动应用程序具有主线程或所谓的UI线程。用户界面的任何操作,用户界面的任何更改都必须在此主线程中发生。如果要更改按钮的颜色或移动按钮的颜色-所有内容都应在UI流中。

另一方面,所有用户交互也在主线程上出现。也就是说,用户单击了一个按钮-我们在主线程中收到一条消息。就像我们的情况一样,更改了文本-我们也在主线程中获取了文本。由于只有一个流并且UI中的所有操作都在其中进行,因此照顾好它并对其进行尽可能少的计算非常重要,否则您可能会面临长时间处理用户操作且其他用户操作不断累积的情况。然后,一切开始冻结。

因此,默认情况下,许多系统库在后台流上运行。例如,到网络的行程平均需要100到500毫秒。对于主流而言,这是相当昂贵的操作,因此与网络的所有交互都在后台流上进行。

同样,这给我们带来了问题,因为如果我们不经意地立即使用从服务器获取的结果来更改用户界面,则可能导致崩溃或崩溃。

回顾我们的最后一行:

self.textOutputView.text = translation

在其中,我们获取了服务器的结果并将其设置在输出字段中。因此,我们违反了第一条规则-我们不从主线程更改UI。标准库Grand Central Dispatch将有助于解决此问题。它很容易地帮助我们切换到主线程并在主线程上执行此操作。

DispatchQueue.main.async {
  self.textOutputView.text = translation
}

让我们最后看看应用程序带来了什么。



用户输入文本,我们看到翻译几乎立即发生。万岁!我们解决了这个问题。但是,在发布应用程序之前,让我们谈谈另一个重要主题-体系结构。

不幸的是,在当前项目中,我将无法向您展示架构的重要性,但它仍然很小。



但是,我向您保证,体系结构并不是源于更好的生活,不是源于开发人员无事可做,而是他们编写抽象程序以免被解雇。架构是对移动开发挑战的答案。

这些问题的主要是可伸缩性。当您的应用程序太大并且具有不同的功能时,重要的是易于理解,扩展和调试。否则,任何新增功能都会更改所有旧功能。而且我们存在错误的风险也会增加。

不要等到您的应用程序增长。刚开始时,您就可以学习构建适用于移动应用程序的软件的基本实践,例如SOLID,四个帮派模式。

移动应用程序的体系结构有其自身的特点:它们的全局或大型组件是根据体系结构模式构建的,该体系结构模式在较高的层次上说明了哪些对象应该属于哪个层。最受欢迎的是MVC,MVP和MVVM。

并且不要忘记,现实中建筑不是万灵丹。有必要考虑项目的细节。如果您眼泪含泪地将某种体系结构引入项目中,则可能出了问题。

当您学习理论时,对您来说这似乎非常复杂。但是实际上,当您在具有良好体系结构的项目中工作时,您会很高兴,因为它使您更容易编写代码。您知道要添加的内容和位置,以便拥有功能。因此,在此阶段,为了更好地了解体系结构,我建议您在大型项目中工作或实习。如果您没有这样的机会,那么现在许多公司将他们的项目放到开源中:Wikipedia,Firefox。而且没有人禁止您访问GitHub并在那里查看。

至此,我们的应用程序准备就绪。让我们将其放在公共领域中,以便用户可以下载它。



在大多数情况下,用户会从Google Play和App Store获取应用。但是在将应用程序添加到商店之前,我们必须对其进行签名。这是由于操作系统仅从受信任的开发人员运行应用程序。因此,在移动平台上,我们只有很少的恶意应用程序和病毒,因为只有受信任的开发人员才能访问在移动设备上工作的权限。

为此,您需要颁发开发者证书。这实际上是一个很小的官僚机构,幸运的是,它在最新版本的Xcode中是自动化的。

另外,您还需要为您的应用程序和说明拍摄屏幕截图。最后两个步骤不应忽略,因为应用程序的页面就是其广告。如果不是很亮,那么很可能我们的所有开发都是徒劳的,因为没有人会下载该应用程序。

该应用程序已上传,现在让我们讨论一些其他技巧,这些技巧可以简化您的生活并提高应用程序的质量。

您最常使用的技能是调试。



主要的调试方法是使用旧的console.log或printf。它有很多名称,但含义相同。当出现问题时,我们添加日志记录和打印变量。但是不幸的是,这种方法也有严重的缺点。

缺点之一是更改源代码。添加printf时,有些错误会消失。然后删除printf-再次出现。这些错误甚至还有一个单独的名称-heisenbug。

第二个结果是您需要重新编译应用程序并再次运行。在大型项目中,这可能需要几分钟的时间,如果在添加每个新日志时需要等待一分钟,那么总共将花费大量时间。

还有printf的最后一个最关键的缺点-不幸的是,它并不能解决所有错误。

个人实践的例子。开发键盘入门时,发生了以下情况:



在下面的系统键盘中,出现了一些标识符,而不是系统地球仪和麦克风图标。调试此错误,我感觉是这样的:



应用程序如何破坏系统键盘?事实证明是可以的。



在调查错误时,调试器知识对我有很大帮助。特别是,设置断点以调用某些函数。查看调试器,在这里我们可以查看我们的用户界面,并查看谁具有哪个类和什么状态。

当我利用前两点时,事实证明问题出在UIKit库中。 iOS开发人员对此很熟悉,并且知道它没有开源代码。但是,当您了解汇编程序时,任何库都将成为您的开源程序,因此汇编程序的一些小基础知识可能会派上用场。

也有所谓的逆向工程技术。有时这很无聊,有时很有趣-一个侦探小说,您在其中研究一个组件与另一个组件的连接方式,以及它们如何在库中完成。结果,事实证明问题出在Objective-C语言运行时中。

下一个重要技能是优化我们的应用程序。



移动设备的资源有限,因此经常会出现性能问题。在开发时,我们需要考虑诸如CPU消耗之类的问题。通常,这就是您编写的代码的复杂性。渲染速度,内存和网络流量,因为大多数用户更可能在移动流量上使用您的应用程序。让我们尊重用户,也许这将是相互的。

第五点是电池,它从前四个开始。

优化应用程序时,最重要的是确定问题区域。如果仅依靠自己的假设,则很可能会浪费大量时间,并且不会获得太多利润。这将有助于平台工具。它们包括一个探查器-该程序向您显示该程序在代码中花费最多时间的位置。也就是说,您将看到程序最常挂起的方法,并且最有可能找到冻结的原因。

了解算法和数据结构将帮助您找到更有效的解决方案。同样,多线程知识可以在这里提供帮助。现在,移动设备上有多核处理器,并且通过在多个线程之间并行化问题,可以使性能略微提高n倍。

有时,不幸的是,前两点没有帮助。然后,您将通过了解操作系统的工作原理以及诸如内存映射(mmap)之类的系统调用知识来获得帮助。在我们的案例中,第三方iOS键盘在RAM消耗方面有限制-52 MB。也就是说,我们要添加功能,创建漂亮的用户界面,但限制为52 MB。目前尚不清楚该怎么办。

添加其他功能时,发生了这种情况。我们经常开始超过此限制,并且不知道该怎么做。结果,内存映射系统调用得以解决。我们从字典中取出一个文件,从中获取所有提示,然后开始调用内存映射。因此,我们处理文件的一部分而不将其完全加载到RAM中。

最后一个经常遇到的问题是开始时间。在这里,我可以建议您阅读代码开始工作之前发生的情况。特别是关于静态和动态链接。



最后一个有用的技能是无聊任务的持续集成或自动化。

没有人喜欢做无聊的任务,因此我们将它们自动化。通常,最简单的方法是为每次提交提交构建应用程序,并且构建应用程序的频率越高,发现问题的速度就越快。如果您有测试,也可以运行它们。

就像我说的那样,该发布与一个小的官僚机构有关,因此它也是非常自动化的,您可以针对每个池请求将程序集释放到beta存储中,以便测试人员可以对其进行测试。您也可以自动为App Store生成屏幕截图,以免手动进行操作。

对于列出的所有技能,我收集了有用的材料。这将有助于他们的学习。它还包含翻译程序简化版本的源代码。感谢您的关注,希望您对开始学习的知识有所了解。

Source: https://habr.com/ru/post/undefined/


All Articles