希望你们中的大多数人熟悉Container View Controller的概念。 这是一个非常有用的Cocoa功能,我发现自己最近越来越多地使用它。 不过,由于您可以在Apple的文档中找到它,因此我将不介绍其实现细节。 让我们深入研究一些我认为超级有用的场景。 嵌入UITableViewController 。 每个人都去过那里。 您有一张桌子,周围还有一些其他内容。 大多数人只是将UITableView添加到其UIViewController子类中。 但是通过这种方式,您将放弃通过UITableViewController免费获得的许多功能,例如: 自动滚动到聚焦的UITextField和UITextView以便它们不会隐藏在键盘后面 默认的UITableViewDatasource和UITableViewDelegate实现 完美无瑕的提拉精神 仅举几例。 如果将UITableViewController放入容器中,您将获得两全其美的UIViewController –您自己的UIViewController子类的灵活性,用于装饰内容和UITableViewController内置功能 2.共享的屏幕部分-出现在应用程序不同部分的屏幕部分。 如果使用CleanSwift体系结构,这将特别有用。 您可以轻松重用完整的场景,并且已经设置了他们的所有助手(交互器,路由器,工作程序)。 3.显示错误和场景的空状态。 4.将其用于控制器动画,因为与使用View Controller Transitions的UIViewController相比,使用UIViewPropertyAnimator和UIGestureRecognizer UIView动画更容易。 像使用其他视图一样,使用嵌入式控制器创建容器视图并对其进行动画处理。 您可以在DisplayInDrawer lib中看到这种方法。 在许多其他情况下, UIViewController包含可以简化程序员的生活。 但是–有一个警告。 假设您有一个嵌入式UITableViewController 。 您刚得到数据,因此创建了一个控制器,注入了数据,将其嵌入并显示。 到目前为止,一切都很好。 新数据到来。 在许多项目上,我多次看到使用相同的例程。 “因此您创建了一个控制器 ,注入了数据,……”。 错了 。 尽管已经有一个控制器,但您无需实例化它。 除非这样做可能很昂贵( viewDidLoad往往很忙,对吗?),否则您可能会引入疯狂的错误,例如注册重复的观察者,完成处理程序等。如果您的控制器分配不正确,这会变得更糟。 尽管我确定您的控制器确实会释放 👮,但由于您进行了仔细检查,不是吗? 解决方案是每次检查控制器是否已经存在,以及是否存在,只需注入数据即可。 不要创建新实例。 但这会变得很乏味,您很容易忘记进行此检查。 输入UIViewController-DisplayChild扩展名,该扩展名通过嵌入(显示) 类型而不是instance来缓解此问题。 您为它提供控制器的类型 ,配置闭包和容器视图。 该扩展程序决定是否需要实例化控制器,如果需要,则创建一个实例,在其上运行配置闭包,并将其嵌入到指定的容器视图中。
今年,我有机会在ioscon 2017上发表了有关Equinux如何为Apple的三个主要平台构建应用程序的演讲。 在多个平台上运输产品会增加额外的开销和工作量,而采用正确的方法和工作流程可以将这两者保持在最低水平。 我们的开发人员在构建适用于iOS和macOS的应用程序方面拥有丰富的经验,他们能够将其应用于tvOS。 我分享了一些经验教训,以及有关如何确定多平台是否适合您的产品以及如何考虑跨多个平台的产品设计的一些技巧。 前往Skills Matter观看完整的谈话 关于ioscon的说明 这是我在ioscon的第一年,我非常兴奋。 演讲真的很好,并且深入探讨了我在其他地方没有看到的主题。 您会感到所有与会者都真正了解他们的知识,并且在大多数会议之后我们进行了一些精彩的交谈。 推荐 !
我们知道挑战是可以帮助我们成长的真正动力。 这就是为什么我们欢迎那些愿意从事需要创新,决心和独特方法来解决尚未解决的问题的人员的人。 如果您发现自己正在研究可以改变旅游行业并为团队带来知识的解决方案,我们将非常乐意与您聊天和喝啤酒。 关于该项目 15toGO是一个平台,它将使旅行者能够与志同道合的人相遇,预订由当地旅行社组织的旅行,并帮助人们前所未有地一起旅行。 我们正在构建的应用程序具有反向用户体验,有可能吸引数百万用户-与其选择先去哪儿,不如让网络参与者首先建立志同道合的人组成的社区,他们可以与他们一起旅行! 我们所知道的分散式应用程序可能会破坏旅游业。 了解有关该项目的更多信息。 质量检查专员 我们即将发布我们应用程序的Alpha版本,我们正在寻找有动力的质量检查人员,他们希望成为不可思议的专业团队的一员。 职责范围 –为不同的项目创建测试用例 –执行不同类型的黑盒测试,包括功能性和非功能性 –监视,跟踪和报告在测试执行过程中发现的缺陷 –跟踪开发人员更改并在需要时进行适当的测试 –使用各种工具和语言自动化测试用例 –为新的应用程序或功能开发和组织测试策略和测试用例 –通过确保我们的软件没有错误,使我们的客户获得最佳体验 要求 – 3年以上软件质量保证经验 –超过1年的自动测试经验 –对SDLC有很好的了解 –流利的英语,书面和口语 –热心,勤奋,有上进心的人,具有出色的沟通能力 –井井有条地组织工作 –承担责任并能够做出独立的决定 – ISTQB认证将是一个加号 毫不犹豫地申请该职位-每个申请都会得到认真调查。 我们提供: —令人满意的薪水 -远程工作的机会 – 灵活的工作时间 —令牌奖励,可用于预订平台上的旅行 —与超级巨星团队合作的机会 iOS开发 我们正在寻找一个技能娴熟,热情高涨的iOS开发人员,他们可以立即加入我们,并帮助我们提供旅行者所期望的最佳用户体验。 职责范围 –在快节奏的工程团队中工作,并帮助推动团队的交付和技术能力前进 –与项目负责人合作,以确保团队提供所需的质量并遵守最佳实践 –积极主动地参与所有任务,并处理冲刺积压项目 –寻找并积极向团队推广想法和技术 –负责从初始设计到交付到生产的任务交付 –了解更改将对负载和性能产生的影响 要求 –经过验证的iOS开发专业经验 –成功交付复杂,高性能和高质量软件的经验 –了解非功能性要求,质量保证和持续改进方法 –精通iOS原生技术(Objective-C,Swift,CocoaTouch,Xcode,Instruments) – REST-API集成经验 –对AutoLayout的深刻理解 –具有编写自定义UI组件和库的经验 […]
几周前,我参加了由CocoaHeadsNL主办的今年在阿姆斯特丹举行的DO iOS会议的第一天。 这也被称为“大学时代”,这是丹尼尔·斯坦伯格(Dim Sum Thought)的作者,培训师和开发人员丹尼尔·斯坦伯格(Daniel Steinberg)在函数编程方面进行的实验性研讨会,在剧透警告时,他是一位出色的演讲者。 Daniel在iOS方面具有深厚的背景,并且对函数式编程非常熟悉。 (很酷的事实:在成为开发人员之前,他曾经是数学教授。) 粗略地说,会议包括一些很简单的东西,一些是中间的东西,有些是某种魔术。 在此博客中,我将分享精彩集锦,以及当天的一些最佳提示,技巧和提示。 *要阅读我们在DO iOS系列文章的第2部分,请单击此处。 首先:函数编程的一些很酷的功能,例如将函数链接到先前函数的结果。 信不信由你,下图是一个包含多次执行“ F”的闭合结构的结构。 之所以有效,是因为每个函数都返回该结构本身的实例。 真好! 该变量称为“ f”,它是名为Picture的结构的一个实例,其中包含一个作为属性的闭包(闭包绘制一个“ F”)。 实际上,只需调用f即可创建第一张图片,如下所示: F 相反,第二个是通过调用: f.quad(空白,f.rotate(),f).quadFlip().quadRotate().quadRotate() 这里的关键是每个函数( rotate() , quadFlip()和quadRotate()返回Picture的实例,从而允许您以功能性方式运行更多转换。 接下来,我们讨论了Swift中几个比较基本的功能编程函数,例如.sorted() .split()或.map() 。 一些创建Swift的开发人员具有此类编程的背景,因此这是今天值得欢迎的补充。 小组中的几乎每个人以前都曾经听说过这些功能,或者曾经使用过这些功能-但是即使如此,Daniel仍可以向我们展示如何使用它们的原始方法。 例如:为了弄清楚句子“ 我看见的是猫吗? ”是回文(向后读取与向后读取相同),您可以编写一个循环以将第一句话的第一个字母与第二句话的最后一个字母进行比较(在小写并删除标点符号之后)。 如果您可以正常工作,则可以执行以下操作: zip(string,string.reversed()).map(==).reduce(true){(累加器&&元素中的(累加器,元素)} 我们还手动实现了一个map函数,以查看引擎盖下发生的事情,这既简单又酷。 在对其进行抽象之后,Daniel遵循了以下建议: “编写抽象时,应从具体到抽象。” 咖啡-还是茶歇! (我是每个办公室都有一个茶人)。 让我们提高水平! 休息后,我们练习实现自定义集。 但是,此集只存储一个包含闭包的变量,而不是存储值。 它看起来像这样: struct MySet {让包含:(T)-> Bool} 要点: 为变量选择一个好名字 。 Daniel甚至开玩笑说MySet有多糟糕,他说:“您应该与团队进行命名讨论。” […]
2018年11月2日,该是DO iOS第二部分的时候了:由CocoaHeadsNL在阿姆斯特丹*主办的会议。 大约有12场讲座(均与iOS开发和Swift相关)以及免费的咖啡和食物,对于渴望继续学习和改进游戏的开发人员来说,这里是个好地方。 我有机会参加了这次活动,并将在这里与您分享一些最令人兴奋的亮点。 让我们潜入吧! *如果您错过了本系列活动的第1部分,请点击此处。 引起我注意的第一个话题是荷兰银行(ABN AMRO)。 舞台上有五位不同的演讲者,每位演讲者都针对不同的主题,分享了宝贵的知识并解释了他们的工作方式。 有两点引起了我的兴趣: 1-源代码管理分支模型。 该团队使用中继而不是标准git-flow进行开发。 他们努力建立一个始终稳定且随时可释放的分支。 他们通常不执行拉取请求(或仅对短暂的功能分支执行请求),而是选择结对编程来解决技术上复杂的问题,并进行提交后审查。 好处: 这种方法消除了解决合并冲突的烦恼 ,它审查了巨大的拉取请求,这些请求通常最终会说“看起来不错,正在合并!” 它迫使您在测试新引入的代码的地方进行小的提交 。 它鼓励您重构代码并保持代码库整洁 (在功能分支中进行重构使审核变得困难,并且可能会导致可怕的合并冲突)。 2-牢不可破的交付管道。 为了使此方法顺利运行,您需要付出巨大的努力来测试代码并建立可靠的交付管道。 以下是交付新产品版本之前需要执行的每个步骤的概述: 就像这张幻灯片所示,团队在测试,代码质量和持续集成/交付上花费了时间。 令我惊讶的是,使用此管道,由于提交前将其提交到远程之前有许多安全点,因此根本不可能中断中继。 团队使用的一些外部工具: SauceLabs在大型仓库中存储的真实设备上运行UI测试。 SonarQube在每次提交后分析代码质量,告诉您代码重复的数量和代码覆盖率。 他们展示的示例覆盖了88%的代码,仅覆盖了3%的代码重复。 挺棒的! 连结以在开发人员之间共享档案。 对我而言,这次演讲表明了为什么以及为什么要不断进行集成/交付是绝对值得的。 换句话说, 在构建高质量产品时 , 不选择不测试代码是不可行的。 我们也可能会在不远的将来尝试使用树干进行开发,它为像我们这样的小型团队带来了很多好处。 另外,我喜欢结对编程的思想,用两个人而不是一个人来解决复杂的问题,从而产生了更加一致和清晰的代码库。 而且上面提到的外部工具值得一看。 另一个有趣的话题是ANWB的David Broza。 David讨论了ANWB的编程方式,如何使用不同的应用程序架构维护干净的代码库以及如何测试代码。 与ABN AMRO一样,ANWB投入了大量精力来测试其代码并使用众所周知的体系结构。 David展示了他们如何注入依赖项以使代码可测试。 ANWB使用自定义汇编程序,这与我们在Mobile Company使用的Swift依赖注入框架Swinject非常相似。 对于单元测试,他们创建了自己的Swift模拟框架-类似于我们使用的Cuckoo框架。 显然,必须编写经过良好测试和架构良好的代码,通过教我们的开发人员为什么以及如何编写可测试的代码,再次确认我们在生产维护良好的代码库中处于正确的轨道。 亚历山大大帝 Griekspoor是一位经验丰富的应用程序开发人员,长期以来一直在开发成功的产品,他分享了有关如何创建Agenda应用程序的故事。 我喜欢听到有灵感的开发人员的故事,但我并不感到失望。 议程—关于Notes的优雅新见解。 议程是一个以日期为中心的笔记应用程序,可用于计划和记录项目。 […]
你好,世界…!! 通过了解Trigonometry的iOS坐标系开始我的第一个博客。 希望初学者对如何使用适当的坐标定位视图有清晰的认识。 首先给我一些介绍。 我从iOS开发开始了我的职业生涯,现在我仍然在从事。 我正在与一家印度(孟加拉)IT公司合作。 数学让生活变得轻松 我完全相信,如果您正在编程,那么您必须精通基础数学,如果您还没有,并开始了程序员的职业,那么从第1天开始,就应该以各种可能的方式将数学计算包括在您的代码中,这是一种实践。向您介绍如何在iOS坐标系中使用三角计算以完美地将视图放置在正确的位置。 现在让我们集中精力…… 在该图中,您可以看到如何定义普通坐标系,这是我们在学校和大学中曾教过的,以及x和y位置相对于左下角的原点(0,0)如何增加或减少。 在下图中,您可以轻松了解iOS中的坐标轴是如何变化的, 原点(0,0)位于左上角,而x和y位置分别增加到左和下,分别覆盖了屏幕区域。 啊哈! 那很简单,不是吗? 但是请记住,在处理CoreGraphics类时,此坐标系在iOS中会再次更改。 现在,让我们继续前进,着手编写代码。 为此,从GitHub下载示例项目 这将使您更好地理解。 示例项目链接: https : //github.com/PriyamDutta/PDFloraButton 这些代码以swift 3.0编写,用于将浮动按钮相对于中心按钮放置在屏幕的不同位置。 转到PDFloraButton.swift文件。 预定义的位置如下: 在旁边的图中,您可以看到子按钮如何围绕它们各自的主按钮排列,并保持相等的间距。 我们要记住的是角度和起点。 跟随下面…… 现在您可以在图中看到必须均匀放置按钮。 因此,您必须在子按钮之间平均分配角度。 不用担心,我们会在一段时间内非常轻松地完成此操作。 但是首先,我们有一个转移原点的小障碍。 改变原点震惊……? 并非如此,您只是为了简化工作而将每个主按钮的中心点视为原点。 怎么样…?? 对于任何圆,您都有中心点和半径 。 在此, 主按钮中心将是具有静态半径的 中心点 ,该半径将决定子按钮与主按钮之间的距离。 在这里,变量anchorPoint将成为中心点。 私人让步半径:CGFloat = 100.0 私人让球周长:CGFloat = 360.0 私人var度:CGFloat = 0.0 私人var anchorPoint:CGPoint! 注意:在玩角度游戏之前,总有一种将 […]
通过谢尔盖·沙巴林(Sergey Shabalin) iOS环境中有四种主要的架构模式,而Bohdan Orlov已将它们全部揭开神秘面纱。 我将尝试指出MVC,MVP,MVVM和VIPER之间的主要区别,这些区别可能会在为您的应用程序构建适当的体系结构时发挥作用。 模型-视图-控制器模式 我认为这是一种基本模式,已被证明是多种技术中的有用工具,对它们的开发有所贡献,并且通常是对开发人员的有用助手。 如果您问建筑师什么是实现此模式的最佳方法,则很可能会获得所有不同的版本和解决方案。 所有模式的一个重要特征是UI与编码逻辑的分离,这使设计人员无需考虑代码即可完成工作。 MVC模式的首次出现归因于SmallTalk语言。 它需要一种架构解决方案,该解决方案必须能够将UI元素与域逻辑分离,并将域逻辑与数据分离。 因此,MVC在其原始视图中由构成其名称的三个类别组成。 细目分类有助于我们更好地了解实体,重用它们并单独进行测试。 让我们看一下类别: 模型是域数据访问和操纵的类别。 域逻辑。 视图是负责图形用户界面元素的类别。 用户界面。 控制器是其他两个之间的中间类别。 它根据View中的动作更改Model ,并根据Model的更改调整View 。 实现用例。 通过将实体划分为模式组件,我们可以定义它们对良好体系结构的贡献,该体系结构具有均衡的负载分配,易于测试以及维护成本低廉的特征。 该模式背后的主要思想是Controller和View依赖于Model,但是Model不依赖于它们。 这使得无论视图和控制器如何,都可以开发和测试模型。 最好的情况是Controller不处理View,并且View可能有多个Controller之间切换。 同样,Controller可以用于多个视图。 例如,一个Controller可能取决于用户登录。用户看到视图并创建一些输入数据,这些数据在从Model订阅通知时被传输到Controller。 视图从模型接收更新,并向用户呈现其最后状态。 模型视图展示者模式 此模式还包括三个组件。 下图说明了视图不必订阅模型更新,控制器(现在为Presenter)将更新通知给视图。 这种方法允许创建抽象视图。 MVP模式的实现可以通过分解View接口来完成。 然后,每个视图将具有其呈现者需要的某些方法和属性集的接口。 该接口由Presenter初始化,Presenter订阅View事件通知并在必要时提交数据。 这种方法允许在应用程序开发中使用TDD(测试驱动开发)方法。 Model-View-ViewModel模式 乍一看,这种MVVM和MVP模式的实现看起来非常简单且相似。 但是,对于MVVM,View to ViewModel连接是自动的,而MVP需要为此执行一些编程操作。 看来MVC拥有更多的View控制机会。 VIPER模式 最后一位提名人特别有趣,因为它不属于MV(X)类别。 在这一点上,我相信您同意分工是一件好事。 VIPER朝着这种分离迈出了又一步,提供了五层而不是通常的三层。 Interactor包含连接到Entities的域逻辑,例如,创建新实体实例或从服务器中检索它们。 为此,您最好使用某些服务和管理器,这些服务和管理器更像是外部依赖项,而不是VIPER模块的一部分。 Presenter包含附加到UI的域逻辑,并在Interactor上调出方法。 实体是简单的数据对象,与与Interactor负责的数据访问层无关。 路由器管理VIPER模块之间的转换。 实际上,VIPER模块可以是您应用的屏幕或整个用户故事。 例如,身份验证过程可以使用一个屏幕或几个连续屏幕。 […]
Moya非常谨慎,以确保测试是小菜一碟。 但是,据某些人称,其测试文档有些分散。 因此,我决定写这篇文章,重点是与Moya进行测试。 我将尝试从Moya的文档中收集到的所有问题以及我自己的贡献来回答这里提出的所有问题。 最终,本文可以用作编写更认真的文档的起点¹。 在我们开始之前:我将假设您… 已经知道如何使用Moya。 如果没有,跳进去,很有趣! 有自己的TargetType 。 我将其称为APIService 。 不要指望本文教给您有关测试的知识。 我也不是高手。 知道(或可以理解)XCTest的一些非常基础的知识。 我选择的是……因为™ 。 准备? 存根 如您所知,在创建APIService时,需要为所有目标提供APIService 。 存入电话时将使用此数据。 但是,显然,如果没有您的明确要求,就不会发生这种替换。 您只需要很好地要求: ¹我实际上要敢于在非我的库中编写文档,然后等待有关本文的一些反馈。 我不是很精通它,或者在测试中。 但我渴望提供帮助。 期待着听到您的意见!
Estéartigo pretende trazer ao seu leitor,软件开发者,软件开发者,可移动iOS应用程序的速记4 SOLID和KISS解决方案的重要性软件quando desejamos construir umasoluçãorobustaesustentável。 Arquitetura软件 从本质上说,使用高质量的语音软件可以通信和使用Carinho。 可以使用部分软件,也可以使用ganhar novas funcionalidades软件。 一种由软件组成的软件,它可以解决软件开发中的任何问题。 Neste linkháum materialtambémescrito por mim quepoderáte explicar mais sobre o problema。 通用软件安装软件鲁棒软件,依赖软件。 界面和接口的实现以及实现的接口。 EstePadrãonos ajudatambém是princípiodainversãodadependência (SOLI D )的代表。 蟒蛇 Como boaspráticas, POO的公用事业概念,通用的公用事业RXSwift公用程序。 Estaspráticas,pro deto的长期运作,nos ajudaram和SOLI D restantes的回应。 没有iOS的重要事项 Este artigoabordaráo或us e dedeçênciautilizando使用了一个故事板 ,并推荐了一个UI。 使用casovocênão,使用nãopoderáusar ométodo 准备(用于segue :) pois作为seguessão类,特别用于故事板 。 […]
最近,我们在标准银行工程部遇到了一个问题,即我们同时运行相同的服务调用。 在任何给定时间都有大量用户使用该应用程序的情况下,任何昂贵且不必要的服务调用都可能给您的后端系统带来巨大压力,并给应用程序以缓慢的感觉。 与往常一样,您可以遵循以下提供的游乐场文件: TYRONEMICHAEL /缓存的承诺 缓存的承诺–使用Promise类型 github.com 解决歧义并提高性能 描述最初的问题 我们有许多不同的功能团队。 如果我们需要特定团队的数据或功能,则该团队可提供面向公众的界面。 使用该接口的其他功能团队不在乎实现。 让我们看一个简单的例子。 这将是面向公众的界面的示例。 现在应该缓存所有服务调用,因此让我们编写一个用于缓存用户的快速接口和实现。 最后是实现公共接口的存储库的私有实现。 让我们退后一步,更详细地说明上述内容。 该实现检查缓存以查看我们是否有当前用户,如果找到用户,则返回该用户。 如果找不到用户,我们将触发服务调用以获取用户。 我们在后台线程上进行所有服务调用,从而防止任何人锁定主线程。 如果在主线程上完成了服务调用,则会引发致命的运行时错误。 提取用户后,我们将填充缓存。 您可以使用以下代码段测试上述内容。 现在,这种方法存在三个主要问题: 无法确定服务呼叫是否已触发并且尚未返回。 因此,我们可以在填充缓存之前发生多个服务调用。 如果我们看一下接口,我们不知道我们必须在后台线程上运行该函数。 是的,该应用程序将在运行时引发致命错误,但我们也不必查看实现。 最后,我们可能会意外地在主线程上调用getCurrentUser()而不是崩溃,因为缓存已被填充。 这是我们需要解决的三个重要问题。 使用Promise解决问题 在开始解决方案之前,重要的是要提及结果类型。 我在我的很多文章中都提到了它,但是基本上一个应用可以处于两种状态之一,即成功状态或失败状态 。 维基百科很好地总结了它。 结果类型提供了一种优雅的错误处理方式,而无需求助于异常处理。 当可能失败的函数返回结果类型时,程序员必须在获得预期结果之前考虑成功或失败的路径; 这消除了错误的程序员假设的可能性。 现在,程序可以进入另一个状态。这就是Promise Type的出现。Wikipedia再次很好地总结了Futures和Promises。 Promise and Futures描述一个对象,该对象充当最初未知的结果的代理,通常是因为其值的计算尚未完成。 基本上,您可以将Promise视为未来的结果 。 因此,更正我之前的陈述,程序实际上可以处于以下三种状态之一: 成功状态 失败状态 等待/未知状态 有很多框架和库影响了Promise或Future Type,但我专门使用Google的框架和库。 通过更新我们的界面: 至: 我们消除了所有歧义。 我们不再需要查看实现以确定是否必须在后台线程上运行该函数。 […]