Tag: iOS应用程序开发

在Swift-3.0中使用协议……

为什么在Swift中需要协议 ? * Act作为接口 * S规定了一组应实施的行为 *您的班级可以遵守的合同合约 *要求|| 方法要求|| 初始化要求 *被选为代表 *用作类型 如何声明协议? 属性要求是什么意思? *协议conformingType必须提供实例|| 具有特定类型&& name的Type属性。 *这里没有约束,必须存储属性|| 计算类型 * C an指定获取|| 设置属性或同时设置两者。 类型属性: 静态关键字为必填项 方法要求是什么意思? *具体的实例方法和类型方法要通过一致性类型来实现。 变异方法要求 更改方法允许更改该实例的属性值。 初始化程序要求: 注意 :初始化器可以是失败的初始化器 如何将协议用作类型? 协议对委派 有何帮助? 代表团 ? :启用结构||的设计模式 班级分担另一个实例的责任。 协议继承: 协议组成 如何仅在类中限制协议? 可选协议要求

我们希望得到的东西是Swift,第1部分

Swift编程语言是一种特殊的东西。 它是最直观,最令人沮丧的语言之一,并且由于苹果建立了庞大的社区,它每年以无数令人敬畏的功能增长。 与Objective-C相比,在Swift中完成许多工作变得更快,更干净! 在DSW,我们使用Swift write 100%编写我们的iOS软件。 我们甚至正在探索使用Vapor之类的工具来编写服务器端Swift(更多内容将在后面介绍)。 但是像许多开发人员一样,我们偶尔会发现自己在Swift的内置类型上构建了有用的扩展,我们希望这些内置类型可以直接使用。 在某些情况下,这些辅助方法最终会在我们的整个代码库中使用,并成为我们体系结构的关键 。 在本文中,我将分享一些我们最常用的辅助方法,以及为什么我们喜欢使用它们。 这些方法在共享框架中定义,并由我们所有的iOS应用程序使用。 也许有一天这些将以Swift语言提案结尾,但是现在您可以随意使用和分享您认为合适的摘录! 从集合(例如数组)中拉出元素的标准方法是使用Collection定义的下标: 如果Index不包含在集合的indices ,则系统将引发异常。 这意味着我们需要首先验证索引,然后访问元素: 上面的例子很常见。 在很多情况下(例如,更新可重用的UI时),如果元素不存在于集合中,则退回到nil至关重要。 我们怎样才能使它更容易? 让我们在Collection上添加一个新的下标,它可以一次将数组越界异常转换为nil : 由于我们的.text属性已经是Optional ,我们现在可以将其转换为单线! 另外,我们的新下标甚至接受Optional作为输入,并将通过方法传播该nil 。 我们可以在感觉满意的任何地方使用该下标,而在其他地方仍然可以使用内置的下标。 真好! 如果您的设计师提供RGBA颜色,您可能会注意到您的代码杂乱无章,如下所示: 我们如何才能缩短此方法调用,消除复制的除法逻辑并仍然保持轻巧? 一种选择是使用HEX值进行初始化,这是完全有效的方法,具体取决于场景。 但是,该逻辑需要字符串验证,提取,扫描和转换为RGBA空间。 不完全是“轻量级”。 事实证明,通过使用可变参数函数,我们可以创建一种超简洁的方法来初始化具有原始RGBA值的颜色。 一探究竟! 现在,创建相同的RGBA颜色变得很容易: 不到原始通话时间的一半! 请注意,我们使用第一个示例中的Collection[safe:]下标来增强此方法的功能。 想象一下,如果没有它,我们将不得不编写多少额外的代码…… 我们甚至可以省略alpha分量,仅在需要时定义RGB颜色。 此扩展不仅缩短了我们的代码,而且避免了整个代码库中的数学错字! 您是否曾经需要将Array转换为Array并发现自己正在与编译器抗争? 开发人员在StackOverflow上已多次要求使用此技巧,但我们对通常推荐的解决方案(使用compactMap (以前为flatMap )) compactMap 。 尽管在某些情况下可行,但此方法是为其他目的而构建的,并且可能产生意外的副作用。 我们发现Senseful的此解决方案是一个很好的方法。 这是我们喜欢的一些东西: 它只对序列进行一次迭代,使我们保持O(n)的复杂度 该方法的名称清楚地描述了其效果 它可以可靠地用于多维序列,没有副作用 解决方案如下所示: 非可选Sequence最后一个扩展是在我们不指定实际上包含可选序列的序列类型时帮助编译器。 […]

iOS Swift新手Gotcha提醒#6-减速带及如何优化XCode 10以加快构建时间!

注意1:编译模式:用于调试的应始终为 Incremental 而释放应为 Whole Module 注意2:优化级别:默认情况下,启动新项目时应正确设置。 您可以通过以下链接阅读有关快速优化的更多信息: Swift 3中的整体模块优化 全模块优化是Swift编译器的优化模式。 整个模块的性能胜利… swift.org 另外,如果您使用cocoapods,则可能可以编辑吊舱的post post安装方法以启用正确的选项,而不必费心处理每个设置。 post_install做|安装程序| installer.pods_project.targets.each做| target | target.build_configurations.each | config | 如果config.name ==’调试’ config.build_settings [‘OTHER_SWIFT_FLAGS’] = [‘$(继承)’,’-Onone’] config.build_settings [‘SWIFT_OPTIMIZATION_LEVEL’] =’-Owholemodule’ 结束 结束 结束 结束 步骤3.减少并发作业数,并为合适的作业获得合适的硬件。 收益递减法则在这里起作用。 您将看到具有更多并发作业以匹配cpu的数量将大大降低构建时间。 建议您在计算机中使用四个以上的内核,以将其减少到5个并发作业。 通过终端命令行输入以下命令,以使用以下命令设置Xcode允许的最大并发作业数。 默认写com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks 5 步骤4.确保XCode10中的“ parallelize build”设置 转到您的方案: 编辑方案>构建>构建选项,并确保并行化构建已打开。 在XCode9中,资源以线性方式构建,这花费了更多时间。 但是,在XCode10中,我们可以利用并行化构建设置来通过所有并行资源大大缩短构建时间。 参考文献: fastred / Optimize-Swift-Build-Times 收集有关优化Swift项目的编译时间的建议。 […]

iOS响应链:UIResponder,UIEvent,UIControl和使用

在上一个操作由UIViewController处理的示例中,UIKit首先将操作发送给了UIView第一响应者-但由于它没有实现myCustomMethod因此视图将操作转发给了下一个响应者–恰好具有该方法的UIViewController在执行中。 尽管在大多数情况下,“响应者链”只是子视图的顺序,但您可以对其进行自定义以更改一般流程顺序。 除了能够覆盖next属性以返回其他内容之外,您还可以通过调用becomeFirstResponder()强制UIResponder成为第一响应者,并通过调用becomeFirstResponder()使UIResponder返回其位置。 这通常与UITextField结合使用以显示键盘inputView可以定义一个可选的inputView属性,该属性仅在响应者是第一响应者(在这种情况下为键盘)时显示。 响应者链自定义用途 尽管Responder Chain由UIKit完全处理,但您可以根据自己的喜好使用它来解决通信/代理问题。 在某种程度上,您可以将UIResponder操作视为一次性通知。 考虑一个几乎每个视图都支持“闪烁”动作的应用程序,目的是帮助用户在教程中导航。 触发此操作后,如何确保仅当前“活动”视图闪烁? 可能的解决方案包括使每个视图都继承一个委托或使用除”currentActiveView”之外每个人都需要忽略的简单通知,但是响应程序操作使您可以使用零委托和最少的编码轻松实现此目的: final class BlinkableView: UIView { override var canBecomeFirstResponder: Bool { return true } func select() { becomeFirstResponder() } @objc func performBlinkAction() { //Blinking animation } } UIApplication.shared.sendAction(#selector(BlinkableView.performBlinkAction), to: nil, from: nil, for: nil) //Will precisely blink the last BlinkableView that had select() called. 它的工作原理与常规通知非常相似,不同之处在于,尽管通知将触发注册它们的每个人,但是这会有效地循环响应程序链,并在找到第一个BlinkableView时立即停止。 […]

在Swift中读取,写入和删除文件

当今大多数普通应用程序都是通过HTTP进行通信的。 虽然我们可以通过这种方式读取和写入数据,但仍然需要将数据保存到设备本地文件中,这仍然非常普遍。 让我们讨论一下如何完成,然后提出一种更简单的方法。 TL; DR 如果您不希望自己学习如何做,请在GitHub上查看我的File项目(但您确实应该知道它是如何完成的,因此请继续阅读!)。 FileManager和URL 刚开始在iOS中进行文件处理时,它会令人望而生畏。 您必须学习FileManager,在您发现需要传递URL之前,它看起来还不错。 然后,您停下来思考:“等等,URL与保存文件有什么关系? 这令人困惑。” Apple选择使用URL作为通用语言来传达文件在文件系统中的位置。 一旦您对这个概念有所了解,它确实非常巧妙。 通过字符串处理文件位置可能会很混乱(我有数十行的旧服务器代码用于遍历目录和文件以证明这一点),但是使用URL会将它们包装在一个非常需要的结构中,该结构相对容易理解和理解。如果您以前使用过URL进行联网,则很熟悉。 即使您以前从未使用过URL,我们所需的基础知识也确实很容易。 实际上,可以将其全部简化为包含三个简单步骤的模式: 1.创建目标目录URL 2.使用目录URL创建文件URL 3.将数据保存到文件URL 让我们看一下这是如何完成的。 注意:如果您以前从未使用过FileManager,请知道它使用Singleton模式,并且不直接实例化FileManager,而是使用FileManager.default来调用FileManager的属性和函数。 如果您不熟悉单例模式,那是确保在应用程序的生命周期中仅实例化类的一个实例的一种方法。 目录网址 首先,我们需要一个用于文档目录的URL。 您不必将所有内容都保存到documents目录,但这是最合乎逻辑的开始,并且一旦您知道如何保存在那里,就很容易保存到其他位置。 我们将使用以下代码来获取文档目录的URL: 让directoryURL = FileManager.default.urls(用于:.documentDirectory,在:.userDomainMask中)[0] 我们在这里要做的是向FileManager索要用户主目录(或在iOS中为应用程序的主目录)中文档目录的URL列表。 这将返回一个数组,其第一个条目将包含documents目录,这就是为什么我们在语句末尾指定[0]的第一个数组索引的原因。 这将返回文档目录的URL对象。 真的就是这么简单。 档案网址 现在我们有了要保存文件的目录的URL,让我们创建文件本身的URL。 为此,我们使用URL(fileURLWithPath:relativeTo:) 。 fileURLWithPath参数中引用的路径是文件名,不包括任何文件扩展名。 例如,如果我们想要一个名为“ myFile.txt”的文件,则fileURLWithPath将为“ myFile”(我稍后将解决“ .txt”扩展名)。 接下来, relativeTo参数是文件将保存到的目录。 该参数带有一个URL ,您猜到了,我们将简单地传入上面的URL : 让fileURL = URL(fileURLWithPath:“ myFile”,relativeTo:directoryURL) 好吧,那文件扩展名呢? 要添加该代码,只需在调用末尾添加appendingPathExtension(:) ,如下所示: let […]

迅捷每周提示— IV

大家好, 我们正在共享“快速每日提示”包。 每周提示列表 默认参数 懒惰的财产 可丢弃的结果 返回多个值 物业观察员 公私(套) 三元运算符 如果您想分享技巧,则可以从GitHub打开请求请求。 您还可以阅读 每周 I, 每周II 和 每周III 。

迅捷代码段#11-RawRepresentable

2017年3月20日,星期一 您可以在这里找到其要点! 上面的代码片段 在每个 RawValue 为 Int 枚举上 创建了 items & itemsCount 属性 。 枚举城市:Int { 案例德里 案例班加罗尔 孟买 } 在以上代码段的帮助下,要获取整个案例列表,我们可以执行 City.items 或 City.itemsCount 来获取计数 🚀 自Swift问世以来,我们所有人最近在我们的应用程序中都使用了Enums ! 而为什么不呢,它们却又超酷又强大。 但是它们有很大的局限性,在这里我们明确需要提供一个computed var得出的computed var来列出所有项甚至项数, 喜欢: 扩展城市{ 静态var项目:[城市] { 返回[.delhi,.bangalore,.mumbai] } 静态var itemsCount:int { 返回items.count } } 上面的代码没什么错,但是它并不出色😓每次添加新案例时,我们都必须更新items ,否则可能会导致bug🐛没有人喜欢它们,我们如何对其进行自动化以使其正常工作盒子和上面的片段😄 非常感谢Nate Cook使其更加出色!!! 🛠️有两个限制 : 仅适用于 RawValue 为 Int 枚举 […]

Swift脚本可在iOS上对本地化字符串文件进行管理

设置完成后,当您的应用程序启动并调用专用的SDK方法进行OTA更新时,您的应用程序将收到下一次启动的 Localizable.strings的最新版本。 请记住这一点! 此外,建议 您冻结先前版本的捆绑软件。 因此,某些更新的值(不是键)将导致 String(format 🙂 崩溃 。 如预期的格式值“版本%s”而不是“版本%@”)或任何翻译错误。 Bundle featurr听起来不错,但: 第一次启动还是网络问题呢? 如果出于任何原因,Lokalise.co不再响应该怎么办? 你明白了。 我们还需要使本地Localizable.strings文件保持最新。 此外,我们需要安全生成的SwiftGen密钥在整个项目中使用它们,因为没有人有时间进行这种类型的行: [[Lokalise sharedObject] localizedStringForKey:@”key” value:@”default value” table:@”table name”]; 通过更新模板模板,我们已经完成了此操作。 要通过Lokalise.co API下载最后一个可本地化的文件,我们可以制作bash脚本,Ruby脚本或Python脚本。 但是 … 创建Lokalise.co Swift脚本下载器🚀 使shell命令可以调用🤓 为了与Swift代码中的shell交互,我们必须编写两个实用程序方法。 它们是使用bash命令编写脚本脚本的关键。 现在,每次开发人员或翻译人员在Lokalise.co上更新您的翻译时,只需运行您的Swift脚本即可将其自动放入您的项目中。 更好:为它创建一个别名 要由项目上的翻译告知更新的键,请不要犹豫使用集成。 我们使用 Slack集成, 每天跟踪更改非常有用。 您可以通过链接直接访问特定的更新或添加的密钥。 创建一个Swift脚本构建阶段以生成复数 等等,SwiftGen不管理复数吗? 是的,SwiftGen尚不管理复数: 解析Localizable.stringsdict文件以支持复数·问题#184·SwiftGen / SwiftGen 我检查了整个存储库,找到了一些有关如何使用Swiftgen处理复数的文档,但是我没有找到…… github.com 您可以为其创建专用的模板或演化版,但是自从我们第一个Lokalise.co Swift脚本以来,我们迫不及待地要编写另一个模板,尤其是我的同事Arnaud🍻。 让我们迅速吧! L10n扩展为复数 我们想要的Swift代码就是这种类型的行: […]

为什么混合动力不是移动的未来

作为一名iOS开发人员,以及在多个面向客户的角色方面都有经验的人,我注意到越来越多的人被混合解决方案吸引,这些混合解决方案是完全本机的替代方案。 吹捧的主要卖点包括减少开发和维护成本以及更快的交付速度。 本文将说明情况并非如此,并探讨使用混合而非本地混合将如何损害应用程序的成功并增加成本。 一直在追赶 进行混合时,您的应用将始终比其本机同类产品落后数月。 可以使用更新版本的Android和iOS,其中包括更新的硬件,新功能(例如Face ID,Apple Pay和Augmented Reality)以及现代化的设计。 谷歌和苹果将分别允许开发人员在发布之前以本地方式访问新功能。 混合社区需要花费大量时间来做出反应和进行调整,因此,在利用新功能方面落后了几个月。 厨师太多 “太多的厨师把汤糟了。” 混合社区存在很大的分歧。 每个公司都认为他们的混合解决方案可以提供最佳结果。 您可以举出React Native,Xamarin和Titanium等几种,每种都具有各自的开发环境-质量各不相同。 每隔两年就会出现全新的混合框架,而现有的框架将变得过时,多余并失去流行性(例如,PhoneGap)。 将旧的混合应用程序迁移到支持较新设备的解决方案上花费了大量的金钱和开发时间。 原生的Android和iOS社区更大,但分散程度更低,并得到了Google和Apple的支持以保持高质量。 工具类 这些工具始终保持一致。 例如; Xcode是iOS开发人员的主要IDE,自2003年以来一直存在。它是功能最丰富,功能最强大的开发人员工具之一,即使最高级的开发人员也可以在其中找到优化工作流程的新方法。 相比之下,本机工具被广泛地记录在案,并拥有庞大的人脉网络来提供帮助,从而大大减少了从构思到应用商店的构思时间。 本机Android和iOS应用程序也更加稳定-随着社区的成熟,更多的调试工具,问题解决方案以及错误处理方式。 混合框架仍处于起步阶段,导致代码更容易出错,破坏了用户体验,并使管理开发时间的预期更加困难。 从来都不是本地人 Android和iOS用户群对他们希望其应用的外观和感觉有一定的期望。 从用户体验的角度来看,它们有很大的不同。 Android遵循Google的Material Design,iOS遵循Apple的人机界面指南。 混合开发人员可以尝试模仿本机应用程序的行为,但要花费两倍的时间才能满足特定的边缘情况和场景。 反过来,代码变得更加混乱且难以维护,因此,在应用程序生命周期的更低端引入新功能将更加困难且成本更高。 混合应用程序会占用手机更多的空间。 如果您选择混合解决方案,请准备排除很大比例的用户,这些用户的手机容量不足或不愿安装太多大型应用程序。 AirBnb在他们的文章中指出,诸如此类的因素迫使他们在使用React Native两年后改回本机。 总结一下 混合解决方案旨在取悦所有人,但它牺牲了最重要的一点:应用程序在用户手中的外观,感觉和行为,从而影响了应用程序的感知性能和质量。 杂种可能认为自己是可行的“两只鸟,一块石头”的解决方案。 我以及其他许多人发现,这需要付出太多折衷,在疏远用户的同时,将时间,开发和维护成本提高到比其本国同行更高的水平。 在DTT,我们专注于提供高质量的本地解决方案,这意味着我们的客户可以获得最佳结果,而成本和时间表却仍是方便且可管理的。 进行混合之前:考虑您要妥协的地方。

构建移动应用程序:首先离线,最后离线!

“由于互联网连接可能不稳定或不存在,因此您需要首先考虑离线:将您的应用编写为没有互联网连接。 一旦您的应用程序脱机工作,请添加您的应用程序所需的任何网络功能,以使其在联机时能做更多。” [来源:脱机优先] 但这很痛苦,对吧? 脱机代码,在线代码,对网络连接的更改做出反应,解决数据冲突,yadda,yadda。 大量的时间和低级的代码花费在移动数据上。 但是,我们必须正确地做。 精心设计的移动应用程序可让用户完成工作,而不会抱怨互联网连接的不足或质量。 在我的工作中,我看到了与Salesforce平台集成的自定义移动应用程序的许多有趣用例,而脱机需求通常最难满足。 因此,我对试用Realm的新对象服务器(其移动平台的后端)非常感兴趣: “ Realm Mobile Platform在服务器和设备之间提供自动和无缝的实时数据同步以及强大的事件处理功能。 您无需再考虑网络代码。 Realm Mobile数据库是跨平台的,同时支持iOS和Android,并且Realm Object Server可以在您的服务器或您喜欢的云上运行。” [来源:Realm Mobile Platform] 听起来很有希望,所以我着手研究如何将Realm Object Server与Salesforce集成。 更具体地说,我想看看是否可以监视通过Realm的示例移动应用程序“ Realm Tasks”进行的数据更改,然后相应地创建和更新Salesforce任务记录。 而且我在短短几分钟内就做到了(好吧,这还不包括阅读Realm文档以及了解如何设置自定义事件监控所需的时间)。 领域对象服务器太棒了! 我在移动设备上修改了数据,该数据几乎立即显示在Realm Object Server中。 我使设备脱机,更新了设备和服务器上的数据,然后看着我重新打开WiFi后毫不费力地同步了本地数据库。 Realm Object Server忠实地通知了我的事件监视器,该事件监视器触发了对Salesforce的API调用。 根本没有用于处理数据同步的代码,只有一个相对简单的Javascript文件即可监视事件并更新Salesforce。 请参阅GitHub上的源代码。