Tag: 工程

从零到英雄:ImmobilienScout24 II上本地应用程序开发的故事

由Mohamed Iyad Tamer Agha撰写 技术 多年来,iOS应用程序的开发中使用了许多技术。 与2011年的标准一样,使用Objective-C作为编程语言。2014年底,Apple引入了一种用于开发iOS / OS X应用程序的新编程语言,称为Swift。 Swift是一种强大而直观的编程语言,它使应用程序的编程变得更加轻松和安全。 而且,Swift是开源的,它使每个开发人员都可以查看Swift的源代码并参与其开发。 为了从Swift的优势中受益,我们ImmobilienScout24于2015年春季开始使用它来编写我们的iOS应用程序的一部分。 团队使用的其他技术是: Xcode和appCode作为开发环境(IDE) git与github和gitlab进行版本控制 XCTest和OCMock用于单元测试 KIF和EarlGrey用于UI测试 HockeyApp用于崩溃监控和Beta测试应用程序分发 NewRelic用于应用程序监视 除了这些技术措施外,我们还在日常工作中采用了许多质量改进措施。 技术措施:自动测试 编写自动测试软件部分的测试已成为生产软件时的行业标准。 不同种类的测试之间有区别。 ImmobilienScout24应用程序的开发过程中使用了三种测试。 单元测试:单元测试用于测试软件的最小可能组件(单元)。 更具体地说,这意味着项目中的每个Objective-C或Swift类都有一个测试功能准确性的单元测试类。 可以使用某些工具来衡量整个项目的测试范围。 拥有2,000多个单元测试,我们项目的测试覆盖率超过80%。 单元测试的另一个方面是所谓的“测试驱动开发”,简称TDD,其中测试是在实际软件组件之前编写的。 然后,以符合测试要求的方式实施软件组件。 在我们的团队中,每个人都知道单元测试非常重要,但是由每个开发人员来决定是在软件组件之前还是之后编写测试。 快照测试:快照测试是一种集成测试,其中保存了应用程序每个屏幕的屏幕快照,并且每次测试运行都用于检查屏幕显示是否有所更改。 因此,在更改程序代码时,可以快速识别应用程序中的显示错误。 使用Facebook开源框架来实现这种测试。 UI测试:在UI测试期间,将自动启动并单击该应用程序,以检查该应用程序中各个屏幕的交互和整体导航是否符合预期。 由于此类测试的可操作性取决于许多变量,因此是一个真正的挑战,多年来,我们尝试了各种工具和框架,以确保此测试的稳定性。 我们目前正在评估一个名为EarlGrey的新Google框架。 持续整合系统 流畅,高效的软件开发过程需要使用持续集成系统(简称CI)。 CI的任务是为每个git commit构建整个软件并执行所有自动化测试。 如果没有错误,将创建该应用程序的版本。 否则,将通知开发人员,以便可以快速修复该错误。 对于我们的应用程序,我们使用Team City作为CI系统。 我们选择Team City是因为它已经成为ImmobilienScout24的标准配置,并提供了我们工作所需的所有功能。 其他CI系统(例如免费的Jenkins)也可以完成这项工作。 应用分析 Apple的Xcode提供了一个有用的工具,称为Instruments,用于分析应用程序的行为。 使用Instruments可以衡量的关键功能之一是应用程序的内存使用情况。 内存是有限资源,应谨慎使用,尤其是在智能手机上。 iPhone的操作系统可能会很快迫使浪费内存的应用程序关闭。 因此,在发布应用程序版本之前,我们曾使用Instruments进行了内存分析。 […]

什么时候在Swift中使用强,弱和无主引用类型,为什么

我们已经在Funding Circle使用Swift已有两年了。 值得unowned一个特定主题是weak引用类型与unowned引用类型的用法。 为什么存在三种引用对象的方式( strong , weak , unowned ),以及何时应使用每种方式。 首先让我们理解为什么引用计数很重要。 Swift依靠ARC进行内存管理。 顾名思义,它对引用计数,以了解是否必须将对象保留在内存中。 这是一个极其简化的解释,要了解更多信息,请参阅Apple的ARC文档1。 在开始之前,请确保我们的沟通清晰。 在谈论变量时,我们指的是Swift引用类型( class和function )。 引用计数对于值类型( struct , enum和basic类型)的工作方式不同。 每当更改值类型时,Swift都会在写入时进行复制 。 这意味着,通常,我们可以假定实际上一个值类型的引用计数最多为1。实际上,这些值还指向一个相同的实例,直到更改其中一个值为止,仅在这时将完成原始值的副本,然后进行更改并将其保留在自己分配的内存中。 这是Swift中的默认引用类型。 每当我们声明变量但未指定其引用类型时,该变量将始终为strong 。 strong引用是指ARC将为变量引用的对象增加引用计数。 这会影响内存管理,因为在引用计数大于零时无法释放对象的内存。 让我们看下面的简化示例: 常量将始终具有强引用类型,因此,当我们声明let balanceConstant ,它将增加内存中Balance对象的引用计数。 每当指向常量的对象所引用的变量更改时,都会创建该对象的副本,并且该副本就是要更新的副本。 与strong引用相反, weak引用对对象的引用计数没有影响。 这意味着,如果我们声明一个指向对象的weak变量,则该对象的引用计数将与以前相同。 让我们看下面的简单示例,这实际上意味着什么: 我们首先创建一个balance变量,该变量将对新创建的Balance对象保持strong引用。 这将增加对象的引用计数并使它等于1。 接下来,我们声明一个weak变量balanceCopy ,该变量将不会更改对象的引用计数。 然后,通过将nil分配给保持对Balance对象的strong引用的balance变量,从对象中删除strong引用。 这使引用计数为零,从而释放了对象,这意味着我们weak balanceCopy变量将没有指向的对象,因此当我们尝试对其进行拆包时,结果为nil 。 与weak引用相似, unowned引用不会增加对象的引用计数。 但是在用法上有几个重要区别。 weak和unowned之间的区别之一是,Swift运行时会为unowned引用保留辅助引用计数。 当strong引用计数变为零时,对象将释放它拥有的所有引用,但是当有无用的引用指向该对象时,该对象自己的内存将不会被释放。 但是该对象的内存被标记为zombie 。 这意味着用户不能依赖于该内存中存储的任何内容,并且在没有安全拆包的情况下访问它会导致程序崩溃。 […]

Xamarin将iOS配对到Mac

Xamarin Form Hello Worldที่ได้ทิ้งท้ายใว้ว่าจะมาสอนวิธีการBuildลงiOSอร่าตรตอนนี้เราจะมาลองกันครับ กนื่องจากiOSเป็OSที่ค่อนข้างเข้มง่วดของAppleและค่อนข้างSecurityสูงเอามากๆและโค๊ดต่างๆนาๆที่จะทำก็ไม่ใช่ว่าจะฟรีทั้งหมดแต่ทางAppleก็ยังพอเปิดโอกาศให้ผู้พัฒนาได้มาใช้ กันได้อยู่ซึ่งวิธีการต่อไปนี้ผมผู้เขียนไม่ได้คิดขึ้นมาเองและไม่ได้จะทำเองและไม่ได้จะทำเยเพราะว่าเค้ามีวิธีการให้อยู่แล้วแต่ผมจะนำเอาส่วนที่สำคัญๆมานะครับซึ่งเข้าไปอ่านได้เลยที่ นี่https://docs.microsoft.com/en -我们/ xamarin / ios /入门/安装/ windows /连接到mac / iOS上的Visual Studio上的Visual Studio上的iMac上的wifi上的。 งนับอเครื่องiMacครับ(สำหรับVMไม่เครลองแต่คิดว่าคงจะทำได้เหมือนกัน) ู้ขั้นตอนนะครับ 注意在按照本指南中的说明进行操作之前,请完成以下步骤: -在Windows机器上,安装Visual Studio 2017 -在Mac上,安装Xcode和Visual Studio for Mac – 安装后必须手动打开Xcode,以便它可以添加任何其他组件。如果您不想安装Visual Studio for Mac,则Visual Studio 2017可以使用Xamarin.iOS和Mono自动配置Mac构建主机。 您仍然必须安装并运行Xcode。 有关更多信息,请参阅Mac自动配置。 注释注释注释注释注释注释注释注释注释注释注释注释注释注释Xcode注释注释注释Xcode注释注释在iMac上运行Visual Studio 2017的新功能在Visual Studio上运行Visual Studio的Visual Studio 2017(Xamarin Studio) ไม่สอนล กันแค่แปลก็พอแล้ว 远程登录iMac远程登录มามาได้ก่อนงนี้งอมาเราจะมาเปิดให้เครื่อง ที่Macเปิด系统偏好设置และไปที่共享窗格。 检查“远程登录”服务列表。 共享远程登录共享Visual Studio 2017共享Windows共享Windows与Mac配对。 งน้าต่าง配对到Macและมีรายชื่อMacและอื่นๆที่เราตั้งชื่อหรือตั้งค่าเอาใว้โผล่มาแล้วให้เราเลือกที่Macที่เราตั้งค่าใว้แล้วเลือกConnect… ถ้านี่เป็นการเชื่อมต่อครั้งแรกจะต้อง登录ก่อนและครั้งต่อไปจะไม่มีหน้าต่างนี้ขึ้นมนมาอีกเลย […]

如何有效地打开拉取请求

拉动请求是任何推送代码的世界级科技公司的必备工具。 它可以确保您的代码正在由其他工程师审核,并增强了被审核者对他们的代码符合工程团队所同意的一组标准的信心。 但是就像每杯️☕一样,质量在PR中扮演着重要角色。 质量低劣的公关人员可能会使被审核者和审稿人的口感不好,这通常是由于抨击和非建设性的反馈造成的。 它可能导致工程师之间的不信任和烦恼,直接影响代码库,甚至影响公司的文化。 但是,有效的PR可以引发有关最佳实践,代码约定和团队标准的良好有机对话。 PR中的代码修改将影响当前和将来形式的代码库。 最终,每个被批准和合并的PR都是构建产品和公司的LEGO块。 考虑到这一点,工程师确定如何打开有效PR的要点非常重要。 有效的公关人员应该就思想共享,最佳实践,工程惯例和团队团结进行对话。 创建有效的PR似乎是一项琐碎的任务,但是许多工程师陷入了不良习惯,甚至没有意识到。 这里有一些技巧,以提高您的PR游戏。 保持拉短要求 在审查代码之前,您如何惹恼其他工程师? 使用10,000行以上的代码更改来打开大型请求。 眼疲劳,背痛和偏头痛只是工程师在滚动巨大PR时遇到的一些副作用。 让您的公关简短,简单,切合实际。 从历史上看,大型PR通常会被迅速批准并合并,因为审阅者会在代码中略过一遍,没有任何评论可望结束滚动。 如果团队完全不关心代码库的健康状况,但是如果您的团队追求质量和维护,请打开小而简洁的PR,作为附带的好处,您的审阅者会感谢您。 公关应该改变多少行没有神奇的数字,但是如果您在跟踪或描述代码在一个句子中的工作时遇到困难,请分拆公关。 另一个好的经验法则是,票证与PR之间的比例为1:1,并且如果票证看起来太大而不能将其分解为子任务票证,则可以确保较小的PR。 请记住,易于阅读的PR假定可以在工程师之间产生良好的对话和协作。 PR不能用于跟踪谁可以更改回购中的大多数线路。 具有较大PR的另一个副作用是,由于分支修改的文件很多,因此需要不断进行重新编制基准,以使分支保持最新状态。 保持简短简短是游戏的名称。 保持评论的建设性 收到非建设性和不完整的反馈是很普遍的,它会使工作贬值,并且不会使有关各方受益。 一些评论甚至看起来更好,因为它可能冒犯或侮辱了打开PR的工程师。 留下建设性的反馈会引起良好的对话。 在评论PR时,有以下一些注意事项: 不要告诉工程师您将如何实施该解决方案。 大家都知道有很多方法可以解决。 仅仅因为审阅者可以用另一种方式来做并不意味着工程师必须以某种方式来实现它。 只要代码遵循一组团队惯例和体系结构,就可以为它开绿灯。 不要过多地关注代码样式,例如多余的空格,而将其他代码放在换行符上。 将这些任务留给小子而不是人眼看。 不要浪费精力查找丢失的代码样式,而要专注于实际的实现。 给予积极的反馈。 给予积极的反馈会鼓励您的工程师。 收到建设性的反馈是很棒的,但是太多的反馈仍然会使被审核者感到束手无策。 我们所有人都打开了PR,以解决一个难题,同情您的被审核者,并告诉他们他们在重构方面做得很好,或者感谢他们修复了一段时间以来令人讨厌的错误。 请勿使用“只是”或“我以为我告诉过你……”之类的词或短语。 这些短语可能意味着受审者应该已经了解了一些事实,但未能使用此知识,而在大多数情况下,受审者对此一无所知。 通过暗示一些标准,可以使他们感到过时和沮丧。 相反,请教您的同事工程师,并为他们指出正确的方向。 每个人都喜欢可以教书,学习并保持友善的工程师。 以下是移情评论的一些示例: 而不是 “仅使用用户模型工厂”, 而是 使用 “签出用户模型工厂,那里的某个功能可能会帮助您尝试完成” 代替 “我不是告诉您不要分配这个Car对象”, 而是 […]

适用于iOS的Swift-ier Tink

自Tink于2013年成立以来,我们的iOS应用程序就建立在Xamarin之上。 在那段时间里,它有数十名贡献者,并且随着Tink的成长而显着发展。 像任何项目一样,我们在此过程中积累了应尽的技术债务,最终超过了我们必须支持的功能数量,并交付了我们认为不如人意的用户体验。 去年下半年,我们着手在Swift中彻底重写Tink iOS应用。 我们借此机会解决了许多此类问题,并构建了具有坚实基础的应用程序架构,该架构将为我们的未来提供良好的服务。 此外,Tink作为一家公司最近经历了激动人心的品牌重塑过程,这是一个将其与全新应用一起介绍给我们的用户的绝好机会。 在接下来的几周中,您将听到我们的一些工程师和设计师的信息,介绍了我们在此过程中学到的经验教训。 我们计划涵盖广泛的主题-从我们的应用程序架构,数据流网络层,设计系统到我们构建的一些有趣的动画和控件。 我们还将开源一些组件,这些组件现在可以为全新版本的Tink提供支持。 Tink的新版本已经在AppStore上发布了几个月,如果您可以尝试一下并告诉我们您的想法,我们将感到非常兴奋。 如果您喜欢制作圆润且精美的应用程序-我们一直在寻找更多优秀的人加入我们。 我要特别感谢我们出色的iOS工程师团队,他们为此付出了很多努力:Jonatan,David,Simon和Kasper; Henrik&Robin令人惊叹的Tink设计团队,当然还有Tink组织的其他成员,都使该项目取得了成功。👏

如何在iOS上调试后台获取事件

注册您的应用以进行后台抓取,使您可以为用户做各种事情……例如更新图标的徽章计数! 但是您应该如何测试呢? 取回操作取决于操作系统…… 我将向您展示如何调试后台获取解决方案以及遇到的陷阱。 首先,在performFetchWithCompletionHandler设置一个断点,以便我们可以验证测试。 接下来,从Xcode的Debug菜单触发获取: 这应该可以正常工作,但这不是最有用的方案。 如果您想像这样进行调试,则可以直接直接调用performFetchWithCompletionHandler方法。 棘手的部分是重新创建完全不加载您的应用程序的情况,iOS将其唤醒以在后台执行。 这是我们遇到的#xcode问题。 编辑应用程序目标的方案,您将看到一个选项,用于模拟从后台提取事件启动。 在模拟器中尝试。 您将永远等待而不会出错。 显然,这曾经在模拟器中起作用。 但是不再。 精细。 让我们尝试使用该设备。 您可能会认为此错误是有意义的。 也许您需要进入手机上的“设备管理”设置,以验证您是否信任开发者证书。 我一般建议这样做,但是这里无济于事。 据我所知,这是一个通用的“超时”错误。 是什么赋予了? 好吧,这是一个错误。 在iOS 11.0.3之后,此功能就中断了。 如果您使设备保持最新状态(在撰写本文时为11.2.6),则将无法测试设备上的后台抓取。 那么现在怎么办? (编辑:自iOS 11.3和Xcode 9.3起,此功能现在可以使用!感谢Marco Mussini) 希望在Apple解决此问题之前,您可以使用较旧的测试设备。 如果您位于双子城,则可以在Livefront停留并使用运行11.0.3的iPhone 7 Plus(在FinalPass上注册-第一小时免费!)。 以此为警告-始终准备有备用测试设备,以及较旧版本的iOS! Sean在 Livefront 与Xcode有着严格的专业关系 。 ps如果您没有设备,但想验证启动顺序,我已经更新了AppLaunchSequence文档以包括后台获取。

如何将动态Swift框架添加到命令行工具

让我们逐步介绍如何尝试向命令行工具中添加动态框架,并讨论每步操作中出了什么问题。 步骤1:将其添加到“链接的框架和库”部分 这是您运行应用程序时发生的情况: dyld:库未加载:@ rpath / libswiftAppKit.dylib 引用自:/Users/seanberry/Library/Developer/Xcode/DerivedData/TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqvuv/Build/Products/Debug/ThirdParty.framework/Versions/A/ThirdParty 原因:找不到图片 ThirdParty.framework尝试在@rpath目录中找到libswiftAppKit.dylib (它是Swift标准库的一部分)。 我们可以看到ThirdParty.framework如何通过运行来定义@rpath $ oTool -l ThirdParty.framework / Versions / Current / ThirdParty 加载命令27 指令LC_RPATH cmdsize 48 路径@executable_path /../ Frameworks(偏移量12) 加载命令28 指令LC_RPATH cmdsize 40 路径@ loader_path / Frameworks(偏移量12) 好吧,开枪。 这些与我们的命令行工具无关。 我们没有任何名为/ Frameworks或../Frameworks的文件夹。 为什么要在其中寻找Swift标准库? 因为它是为iOS和Mac应用程序构建的。 这是Mac应用程序中的目录结构: 那解释了path @executable_path/../Frameworks 对于iOS,应用程序内部的目录结构为: 这说明了path @loader_path/Frameworks (offset 12) 但是,谦虚的命令行工具开发人员呢? Swift标准库在我们的可执行文件中静态链接,但是我们的第三方框架找不到它们。 不幸的是,它们并没有存储在每台Mac上的标准位置。 开发人员可以访问埋在Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx […]

Swiftコンパイラの警告を无视できないようにする

Swift / iOS界隈では可选(2018年) そしてmonoさんがツーイートされたSWIFT_TREAT_WARNING_AS_ERRORS = YESは, SWIFT_TREAT_WARNING_AS_ERRORS = YESではなくエラー(🚨)にして无视できないようにします。 Xcode发行说明 描述Xcode中的新功能和已知问题。 developer.apple.com 添加了两个新的构建设置以启用Swift编译器选项: -禁止警告(SWIFT_SUPPRESS_WARNINGS) 错误警告(SWIFT_TREAT_WARNINGS_AS_ERRORS) 这些设置与相应的clang选项的构建设置无关。 (24213154) SWIFT_TREAT_WARNING_AS_ERRORSで検索すると见つけやすいです。 こうすると,これまでは警告で无视できたものがエラーになって无视できず,コードを修正しない限りリリースできなくなります。 可选(2018)年あけましておめでとうございます| 工程师博客 エ早々,大変お騒がせしております。申し訳ありませんの一点に尽きます。はてブや,Twitterなどで大きく话题にしていただいたので,この机会に,耻は承知の上で,なぜこんなことが起きてしまったのか,笔をと… moneyforward.com 非常に大きなサイズのPRであったことや,破壊的変更が行われたSwift 3への対応だったこと,そもそも古くから运用されているプロダクトであるがゆえの大量の警告を全て溃しきれておらず,そのまま埋もれてしまったとしか言いようがなく,とても耻ずかしい限りです。 たしかに理想は「リリース前に対处しておくべき」ですが,开発现场ではこのようにさまざまな事情があるでしょう。 転职がさかんな企业家ですのでどういう経纬で警告を无视してきたのか谁もわからない现场もありそうです。 ここで绍介したSWIFT_TREAT_WARNING_AS_ERRORS = YESにすることはあくまで対策のひとつです。 ,警告はすべて确认して解消していくべきですね。

与Jenkins,Xcode和GitHub的基本持续集成

在上一篇文章中,我论证了为什么单元测试和代码审查很有价值。 在这一篇中,我将向您展示如何建立一个自动化系统来执行这些原则。 在允许PR合并之前,我们将要求有人对其进行审查,并且所有单元测试都已通过。 开发人员在提交PR之前不应该运行单元测试吗? 是的,但是拥有护栏并没有什么可耻的。 专家通常会忘记一两个细节。 看看医院开始允许护士对医生实施检查清单时发生了什么。 2001年,约翰·霍普金斯医院的重症监护专家Peter Pronovost决定尝试[检查清单]……他和他的团队说服医院管理部门授权护士在发现医生跳过检查清单的步骤时停止医生治疗…… Pronovost和他的同事们监视了一年后发生的事情。 结果是如此惊人,以至于他们不确定是否要相信: 十天的线感染率从11%降至零。 因此,他们又跟踪患者十五个月。 在整个时期内仅发生了两次线感染。 他们计算出,在这家医院中, 清单已预防了43次感染和8例死亡,并节省了200万美元的成本 。 https://www.newyorker.com/magazine/2007/12/10/the-checklist 由于可能会出现错误,为什么不解释这些错误呢? 我们可以告诉计算机强制执行我们自己设计的清单。 有3个主要部分可实现这一目标: 设置Jenkins以构建和测试iOS应用 获取GitHub以加入Jenkins以触发构建并报告测试结果 配置GitHub阻止PR,直到所有检查通过 您将需要Jenkins在Mac上运行。 如果您不能这样做,请立即保释。 👋 Jenkins有大量的插件可以使您的生活更轻松。 我们想要的是: GitHub,GitHub API,GitHub身份验证和GitHub Pull Request Builder —与GitHub交互 JUnit —报告单元测试结果 Xcode集成-帮助我们构建iOS应用 要安装插件,请转到主页->管理Jenkins->管理插件。 然后检查“可用/已安装”选项卡。 您可能已经安装了其中一些! 首先,让我们构建我们的应用程序。 进行Freestyle作业,然后输入您的回购URL和凭据并指定您的主分支: 接下来,浏览至Xcode部分,并将其放入常规设置。 该插件的作用是在您的项目中运行xcodebuild ,并使其易于配置参数。 现在转到Advanced Xcode build options-> Advanced build settings 看到“目的地”参数了吗? 这指向您要测试的特定设备。 […]

掩盖用户的敏感数据-它是私有的。

作为应用程序开发人员,我使用Apple的iTunes Connect检查销售情况。 当您为应用程序提供背景信息时,它会模糊所有销售数据(非常酷!) 他们为什么这样做? 好吧,Apple建议您将其作为最佳实践,因为iOS会为您的应用创建快照并将其存储在文件系统的缓存中。 您可以通过下载iExplorer自己查看。 这仅适用于您在App Store以外(例如通过Xcode)安装的应用。 否则它将被隐藏,除非有人越狱了您的手机。 您可能会说,嘿,如果有人拥有我的手机并且知道如何越狱……他们可以访问我的应用程序的最新视觉状态在我要担心的事情上并不重要。 我明白了 但是另一方面,如果某些事情是可以预防的,那么防止它们仍然是一个好主意。 这就像决定是否要吃最后一个曲奇,即使您一次坐着吃完了盒子的其余部分。 您仍然可以选择不吃最后一个cookie,这样会更好。 实际上,安全公司建议在审计过程中从iOS的快照功能中隐藏敏感数据。 您会注意到所有银行应用程序都这样做。 (请参见顶部的gif。)他们的解决方案有些手。 无论您在应用程序中的什么位置,他们都用公司的初始屏幕覆盖了所有内容。 我不怪他们。 他们可能从Apple的示例中复制了该技术,该示例向您展示了如何使用Objective-C用纯黑视图控制器覆盖所有内容。 让我们做得更好。 协议DisplaysSensitiveData { func hideSensitiveData() func showSensitiveData()//我们弄得一团糟,我们将其清理干净 } 将该协议扔到您要保护的任何视图控制器及其容器视图控制器上。 例如,UINavigationController: 扩展UINavigationController:DisplaysSensitiveData { func hideSensitiveData(){ 如果让vc = topViewController为? DisplaysSensitiveData { vc.hideSensitiveData() } } func showSensitiveData(){ 如果让vc = topViewController为? DisplaysSensitiveData { vc.showSensitiveData() } } } 最后,挂接到UIApplicationDelegate以便在应用程序后台运行或返回时进行适当的调用。 func […]