Tag: 移动

创建一个iOS基础项目

该项目的想法是在开始新项目时用作模板。 它将包含3个构建配置: Debug , AdHoc和Release 。 我们将使用Fabric集成CocoaPods以分发应用程序,然后使用FBTweaks和来自Facebook的很棒的库。 我们将从创建一个应用程序ID开始。 在会员中心 转到证书,标识符和配置文件 : 然后转到“ iOS应用内的标识符”部分: 然后点击屏幕右侧的加号(+) , 并输入应用ID说明。 为您的应用ID使用正确的描述。 您以后可以更改它。 然后,输入一个App ID后缀: 这将是永久的,因此请三思而后行,因为您以后将无法更改它。 然后,选择完所有功能后,点击Submit 。 现在,我们将创建三个配置文件:一个用于开发 ,另一个用于AdHoc分发我们的应用程序(例如与QA团队内部分发该应用程序,并向我们的客户进行每周构建),最后一个用于Release 。 转到“ 供应配置文件”部分,然后单击加号(+) 。 然后,选择iOS App开发选项,然后点击继续 。 然后,选择先前创建的应用ID,然后点击继续 。 然后,选择要包括在“配置文件”中的证书,然后单击“ 继续” 。 然后,选择要包括在Provisioning Profile中的设备,然后单击Continue 。 最后,为Provisioning Profile选择一个名称,然后单击Generate 。 我们将对AdHoc和Release配置文件执行相同的操作。 再次单击加号(+) 。 现在,选择“ 临时”选项,然后单击“ 继续” 。 再次选择先前创建的应用程序ID,然后单击继续 。 现在选择一个有效的分发证书,然后单击继续 。 然后,选择要包括在Provisioning […]

优化Xcode构建以加快Fastlane

持续集成的最好部分是能够自动运行测试并构建可部署的应用程序。 但是,自动构建并不意味着智能或优化的构建。 这是我在加快交付过程中收集的一些技巧。 在进行改进之前先进行测量,然后进行全新清洁大约需要6分钟。 在持续集成方面,我在服务器上使用Fastlane,这大约需要30分钟。 这些通道包括清理,运行测试,然后构建并最终部署到Fabric。 让我们看看如何改善这些时间,一次解决一个问题。 代码优化 代码表达式越复杂,编译器花费在编译器上的时间就越长。 以下是应避免的示例: return CGSize(width: size.width + (rightView?.bounds.width ?? 0) + (leftView?.bounds.width ?? 0) + 22, height: bounds.height) 为了找出应用程序的哪一部分需要花费大量时间来编译,开发人员将构建时间分析器组合在一起。 借助此工具,您可以快速识别和改进代码,从而快速赢得构建时间。 您还可以在Xcode本身中创建特定的警告来标记需要花费太多时间编译的代码。 项目优化 首先,我首先删除了我没有注意到的不必要的代码。 我的意思是一段时间后,如果您使用Cocoapods管理库,那么您可能还会拥有不再需要或不再使用的代码。 为此,我使用了pod deintegrate && pod install 。 第一部分将完全从您的项目中删除Cocoapods依赖项,然后第二部分将重新安装它。 这样,我设法删除了数百个未使用的文件,这意味着编译时删除了数千行代码。 加快构建时间的另一种方法是使用快速模块优化。 我绝对建议您查看Apple文档Swift.org-Swift 3中的整体模块优化。 实际上,在项目的“ 构建设置”下的“ Swift编译器”部分中,您可以自定义“ 优化级别” 。 但是,如果您想保持调试应用程序的能力,则不选择“整个模块优化”。 一种变通方法是仍然能够调试您的应用,将其标记保持为-Onone ,但您必须将SWIFT_WHOLE_MODULE_OPTIMIZATION添加为YES作为自定义用户设置。 通过这些更改以及清理项目后,我的构建时间从5’50”转移到3’15”,几乎是一半的时间。 现在让我们看一下持续集成方面。 快速通道优化 我使用Jenkins使用Git flow和Fastlane自动构建和准备新的iOS更新。 […]

iOS开发人员设置:清理,准备

从干净的石板开始,并添加必需品:rvm,npm,自制 这篇文章是有关设置iOS开发环境的系列文章的一部分。 我上一次设置iOS环境时,我的Mac已作为学生机器使用了多年。 我在数十个教程中都失败或部分安装。 我有用于语言的SDK,我再也不会碰。 在开始设置环境之前,我清理并清除了所有可能的旧应用程序和安装。 如果您是从一台闪亮的新机器或全新安装开始的,则可以跳过第一部分。 塔布拉罗莎 您需要自行决定清洁机器的认真程度。 因为我不信任几年前愚昧无知的安装完整性,所以我清除了ruby,rvm,rbenv,gem,postegres,sqlite,node,javascript和bundler。 万一我弄坏了东西,在清洁过程之前克隆硬盘驱动器就给了我一个安全网。 删除所有内容后,我确认系统已在运行且稳定,因此再次克隆,以便在安装出现问题时可以重新使用。 Ruby和RVM(红宝石版本管理器) 安装rvm来管理您的ruby版本。 这将安装rvm和Ruby的最新稳定版本。 \ curl -sSL https://get.rvm.io | bash -s稳定–ruby 您可能需要根据所使用的宝石和Cocoapods版本在Ruby的不同版本之间进行切换。 除了最新的稳定发行版,这些是我安装的版本: rvm安装2.2.3 rvm安装2.4.0 列出可用的版本,并将2.2.3(或您的首选版本)设置为默认值: rvm列表已知 rvm-默认使用2.2.3 家酿 是否安装了自制软件? 酿造-v 如果没有,请继续并立即安装。 将以下内容复制并粘贴到命令提示符中,然后按Enter。 /usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)” 如果您有自制软件,请更新并运行医生。 解决出现的任何问题。 酿造更新 酿造医生 尝试酿造更新时权限错误的快速修复:“ / usr / local error”: 须藤chown -R $(whoami)/ usr / local […]

使用iOS 10预提取API增强平滑滚动

在上一篇文章中,我们探讨了一些常见的策略来实现iOS移动应用程序中的平滑滚动。 应用这些策略的主要目的是避免混乱的滚动 ,这是对用户体验产生负面影响的常见问题。 为了帮助开发人员完成这项任务,Apple对iOS10中的UICollectionView进行了一些非常有用的更改。 但是,在审查此新引入的功能之前,让我们先检查促使他们需要这些功能的原因。 是什么导致滚动不稳定? 您是否曾经与某个偶尔出现断断续续的滚动的应用程序进行过交互或工作过? 如果答案是“是”,那么当您尝试快速滚动并且应用程序内容似乎断断续续时,您就会知道它多么令人失望。 您可能已经问过自己,是什么触发了这种不稳定的滚动行为以及随之而来的不良用户体验。 简短的答案是:该应用丢帧了 。 但这到底是什么意思? 为了确保一致的平滑滚动,应用程序需要能够稳定显示60 FPS(每秒帧数)。 或者,换句话说,应用程序需要每秒刷新其内容60次。 这意味着每个帧大约要渲染16ms(1000ms / 60帧〜16ms /帧)。 在不幸的情况下,显示一帧所花费的时间比分配的时间长,下一帧将不会显示任何数据,并且据说该应用程序“ 丢弃了一帧” 。 下图说明了这种不幸的情况。 蓝色标记表示绘图操作,其厚度表示完成渲染所需的时间。 如我们所见,在第二帧中,我们发生了一些渲染事件,这些事件花费的时间超过了分配的时间(〜16ms),因此,第三帧已被删除。 我们可以从刷新操作所花费的CPU时间的角度来可视化同一场景。 在下图中,尖峰对应于当应用花费超过预期的〜16ms来刷新当前内容时发生的丢帧现象。 为了获得良好的用户体验,刷新时间必须始终低于允许的最大值〜16ms。 理想情况下,由于我们希望创造出色的用户体验(而不仅仅是一个好的体验),因此每次刷新时间应为: 始终低于允许的最大时间(〜16ms)。 尽可能地低,以节省可用于其他任务的CPU时间。 丢失帧的最常见来源是从主线程为单元加载昂贵的数据模型。 这种情况的典型示例是: 从URL加载图像。 从数据库或CoreData访问项目。 在iOS10中,Apple对单元格的加载和显示方式进行了一些优化。 让我们看一下iOS10可用的改进,以及它们如何使开发人员更轻松地创建流畅的滚动用户体验。 iOS9中的单元生命周期 UICollectionViewCell的生命周期可以如下所示: 集合视图及其单元之间的主要交互是: 收集视图正在请求要显示的单元格的内容,该单元格将要输入可见字段: collectionView(_:cellForItemAt:) 。 集合视图要求显示该单元格- 该单元格刚刚输入了可见字段: collectionView(_:willDisplay:forItemAt:) 。 集合视图正在删除单元格- 该单元格在可见字段之外 : collectionView(didEndDisplaying:forItemAt:) 。 iOS10中的单元生命周期 在iOS10中,单元的生命周期与在iOS9中基本相同。 但是,有一些显着差异。 […]

带有协议和keyPath()的更安全的Swift应用程序设置

协议+ #keyPath +计算属性=强大的用户设置💪 保持应用程序设置同步,持久化以及分配默认值可能会变得混乱。 UserDefaults是一种存储非敏感应用程序设置的好方法。 但是,由于其本质是键值结构,因此我们需要诉诸使用字符串存储数据的方法。 FL红旗! 这是一个等待发生的问题。 简单的拼写错误可能会导致我们访问无效值,或者无法正确更新值。 使UserDefaults更安全👷 Swift 3及更高版本配备了出色的#keyPath()表达式。 这可以使我们避免以类型安全的方式在UserDefaults中使用字符串。 #keyPath()仍使用Objective-C运行时,并将解析为其引用的路径的字符串。 因此,密钥需要通过@objc装饰器公开给Objective-C。 将密钥包装在协议中可以使我们公开整个协议并干净地访问它们: 越来越好… 好。 所以这可行。 目前可能看起来有些令人费解,但是使用协议将使我们可以为下一步使用一个干净的接口。 添加计算属性 “正在计算…” –🤖 使用此约定,我们可以让协议定义我们的设置,无论它们是Bools,String还是其他。 然后,我们可以创建一个符合协议的对象AppSettings ,并使用计算的属性,可以安全地直接从UserDefaults设置和获取变量! 编译器还将强制执行协议,以确保您不会忘记实现所有设置! 👍 哦,看起来很好 我们的设置现在真的开始变得生动起来了。 您还将注意到,如果UserDefaults中不存在,我们的useAmbientLight变量将被设置为false -这是我们可以为每个设置指定默认值的方式! 设置可以轻松检索! 十分简单。 更深入 大! 我们有一种方法可以轻松安全地存储,设置和检索变量。 但是其他类型,例如字符串呢? 如果您有很多设置怎么办? 破坏我们的协议并使用扩展可以帮助清理我们的课程。 使用上面编写的value(for key:)函数,我们可以轻松获取任何其他UserDefault支持的对象(如String),甚至是Optionals的设置! 完整的例子 包起来 #keyPath,协议和计算属性的组合是为您的Swift应用程序中的设置提供强大功能的强大功能组合。 添加设置就像将其添加到现有协议或创建新协议一样容易。 如果您忘记实现一个,编译器甚至会警告您。 希望这种有趣的实现设置的方式在您的应用中同样有用useful。

永别了,2018年:你真棒!

对于Bitrise来说,2018年是很棒的一年。 我们不断添加新功能,以增强我们现有的功能,并且我们也增长了很多。 没有您的反馈和贡献,我们无法做到这一点,谢谢! 现在,让我们看看细节! 比特升🤖 January 1月初,我们不得不快速达到0到100的速度:我们在春季的大部分时间里都欢迎 从Buddybuild迁移到Bitrise的 开发人员和公司 。 我们确实希望所有人都对Bitrise感到欢迎。 Bit新的Bitrise外观的前两批于2018年到货:6月重新设计的着陆页和11月的仪表板 。 敬请期待。 我已经看过了,看起来超级傻瓜酷,相信我。 pricing至于我们的定价计划,我们淘汰了Hobby计划,并推出了Developer计划 ,价格降低了10美元。 在此感谢您的所有贡献,我们现在为Bitrise上的开源项目提供免费的开发人员计划功能 。 November 11月, Bitrise在东京度过了两个非常成功的测试之夜(请参阅此处的所有Tweets),并且在贡献者的帮助下,我们开始将很大一部分文档本地化为日语。 (快来了。) always我们一直对用户如何使用Bitrise感到非常好奇:我们解决了哪些问题以及如何解决。 他们肯定会讲一些很棒的故事。 这就是我们启动 客户成功案例中心的原因 。 to除了规模较小的团队和初创公司之外,我们还为企业客户提供 专用的订阅计划,其中包含可用的自定义托管,安全性和支持功能。 🤖随着我们团队的快速成长,并在一年内翻了一番,达到40人,我们终于搬到了我们了不起的全新办公室 。 您看过我们的Instagram个人资料吗? 查看我们的团队和办公室。 嘿, 我们还在 招聘 ,快来加入我们吧! 新功能亮点 我们推出了大量令人印象深刻的新功能,因此我选择了最有趣的功能。 适用于所有平台 🔀每个工作流程堆栈选择 :为您为应用程序设置的工作流程选择不同的堆栈将为您提供一些方便的新工具。 with通过构建缓存在构建之间传递工件 :可以使用Cache:Push和Cache:Pull步骤在构建之间传递工件,如果要使用一个构建中的文件在另一个构建中生成的文件,这非常方便。 🔒我们进行了一系列安全改进 : 我们介绍了受保护的秘密 我们添加了敏感的输入 加强帐户安全性, 您可以设置API令牌的到期时间。 with 使用相同的触发器启动多个构建 -您知道的应用越多,所需的省时方法就越多,我们知道。 通过在多个并发上并行运行构建,检查我们用于扩展构建的两个步骤。 […]

Swift中的保护套

您最可能听说过if语句,可以将switch情况视为if的更高级形式。 要启动switch语句,请告诉Swift您要使用哪个变量运行事物,然后提供可能情况的列表。 Swift将首先找到与您的代码匹配的大小写 ,然后执行它,然后退出开关 。 这是一个简单的例子: 即使您认为自己的案件将始终执行,也需要使用默认值:重新使用。 多种情况 让我们添加更多案例并利用更多类型的条件。 我们有一个像上次一样的数字,尽管这次我们将检查每种情况下的数字范围 。 像这样: 要检查范围,您只需使用三个句点,如下所示: 1…100 自从第一个以来,没有任何改变。 我们只是添加了更多案例,并检查了一系列数字,以证明您在案例中可以做什么。 差不多了!

使用diff框架更新Swift中UICollectionView数据的更好方法

熟悉的朋友 通过iOS中的UITableView , NSCollectionView ,macOS中的tvOS或NSTableView , NSCollectionView NSTableView ,很难想象没有使用表视图或集合视图的应用程序。 大多数时候,我们从后端,缓存和过滤器中获取数据,以列表或网格形式显示该数据。 之后,当数据更改时,我们将更新您的界面以反映某些项目已被插入或删除。 那就是您最喜欢的函数出现的地方reloadData 。 这样,整个列表将以全新的内容刷新。 当您需要快速刷新内容的方案时,这是很好的选择。 但这会使UITableView再次使单元格大小无效,这会降低性能。 此外,如果这些更改应引起注意,并且您想让用户更好地了解发生了什么,那么最好手动插入和删除行。 如果您使用的是Android,则可能知道不用调用notifyDataSetChanged ,而可以使用提供的DiffUtil为我们计算更改,从而使RecyclerView更新变得容易。 不幸的是,您在iOS中没有那么奢侈,但是我们可以学习如何做到这一点。 本指南以UICollectionView为例,但UITableView行为相同。 对于在Google上搜索NSCollectionView任何人来说,这都有点困难: 拖放 让我们看UICollectionView情况。 想象一下一个应用程序,在该应用程序中,用户可以通过将项目从一个集合移到另一个集合来自定义其体验。 您可以看一下示例DragAndDrop,它在iOS 11中使用了新的拖放API。 在UICollectionView上调用更新方法之前,必须确保数据已更改。 然后我们调用deleteItems和insertItems以反映数据更改。 UICollectionView为您执行漂亮的动画 索引与偏移 在我们进行进一步讨论之前,我只想提及一下,实际上是指从一开始的offset 。 如果您看一下枚举函数,它建议使用名称作为偏移量而不是索引 编辑距离 手工进行这些计算非常繁琐且容易出错。 我们可以使用一些算法来构建自己的抽象。 天真的是Wagner-Fischer算法,该算法使用动态编程来告诉两个字符串之间的编辑距离。 编辑距离是指从一个字符串更改为另一个字符串所需的步数。 字符串只是字符的集合,因此我们可以推广这个概念以使其适用于任何项目集合。 而不是比较字符,我们要求项目符合Hashable 。 从“套件”到“ kat” 我们如何将“套件”一词的形式转换为“ kat”? 我们需要执行哪种操作? 您可能会说“只是将字母i更改为a”,但是这个简单的示例可以帮助您理解算法。 让我们开始吧。 删除项 如果从“ kit”转到空字符串“”,则需要删除3次 “套件”->“”” 3个删除项 “ […]

在Swift中编写网络层:面向协议的方法

在本指南中,我们将研究如何在没有任何第三方库的情况下在纯Swift中实现网络层。 让我们直接跳到它! 阅读指南后,我们的代码应为: 面向协议 易于使用 易于实施 输入安全 使用枚举来配置端点。 以下是我们最终将通过网络层实现的示例: 只需输入router.request(。 借助枚举的力量,我们可以看到所有可用的端点以及该请求所需的参数。 首先,一些结构 当创建任何东西时,拥有结构总是很重要的,因此以后找东西很容易。 我坚信文件夹结构是软件体系结构的关键因素。 为了使文件井井有条,让我们事先创建所有组,然后记下每个文件的存放位置。 这是项目结构的概述。 ( 请注意,名称仅是建议,您可以根据自己的喜好命名课程和组。 ) EndPointType协议 我们需要的第一件事是定义我们的EndPointType协议。 该协议将包含配置端点的所有信息。 什么是端点? 好吧,从本质上讲,它是一个URLRequest及其所有组成部分,例如标头,查询参数和主体参数。 EndPointType协议是我们网络层实现的基石。 继续,创建一个文件并将其命名为EndPointType 。 将此文件放在“ 服务”组中。 (不是EndPoint组,我们将继续进行说明)。 HTTP协议 我们的EndPointType具有构建整个端点所需的许多HTTP协议。 让我们探究这些协议的含义。 HTTP方法 创建一个名为HTTPMethod的文件,然后 将其放在“ 服务”组中。 该枚举将用于设置请求的HTTP方法。 HTTP任务 创建一个名为HTTPTask的文件,然后 将其放入“ 服务”组中。 HTTPTask负责为特定端点配置参数。 您可以添加适用于您的网络层要求的任意多个案例。 我将提出请求,所以我只有三种情况。 下一节将讨论参数以及如何处理编码参数。 HTTP头 HTTPHeaders仅仅是字典的别名。 您可以在HTTPTask文件的顶部创建此类型别名 。 公共typealias HTTPHeaders = [String:String] 参数和编码 […]

Desmistificando通用链接

不能进行自然运动的Alémdeoferecer umaexperiência移动设备,istoé,sem的preprear abrir网站,conconúúdo的深层链接,tambémpodem serótimasferramentas de engajamento para seu aplicativo的深层链接。 Atravésdeles,使用Google的直接复制功能。 Alémdisso,解释性应用程序,trazendo maisinstalaçõespara o app。 通用链接 在iOS 9上,这是Apple的lancom深度链接chamada Universal Links。 URL解决方案的Eles vieram para替代品和解决方案的问题,例如: 链接 :HTTPS Para o seu网站的通用链接。 徽标,应用程序和应用程序定义了os链接; Flexíveis :Universal Links的功能和应用程序的安装,以及所有Safari嵌套的链接; Privacidade :Outras应用程序可用于comunicar或其他应用程序,可用于saber se elaestáinstalada ounão。 兰卡门大公国,维梅拉·坦贝姆·瓦里亚斯·杜维纳斯·索菲尔·芬奇纳门托和实施者。 在通用链接上没有应用程序,在大多数应用程序中都无法使用VivaReal,而在大多数解析器中都存在问题,请使用caminho。 ✌️ 实施通用链接 必不可少的2通用应用程序seu app com通用链接。 Criar o arquivo apple-app-site-association (关联文件)和fazer上载dele no seu网站HTTPS; Tratar o comportamento dos不会造成重复操作。 Criando […]