Tag: swift

如何在Swift中将GIF添加到UIImageViews

我正在制作一个包含gif的漂亮的小应用程序。 我使用了SwiftGif(一个很酷的UIImage扩展)来协助我完成这项任务。 按着这些次序: 如果您没有安装CocoaPods,请安装CocoaPods。 如果您的Xcode项目中还没有Podfile,请创建一个。 您可以通过在终端中键入“ pod init”来创建一个。 您会注意到,我的应用程序名称为“ Should_I_App”。 3.使用文本编辑器打开Podfile(我使用Sublime,它比TextEditor更好)。 如果使用Sublime,则可以键入“ subl Podfile”以在Sublime中打开Podfile。 4.在Podfile的“目标”下添加“ pod’SwiftGifOrigin’,’〜> 1.6.1’” 。 保存并关闭。 5.返回终端,输入“ pod install”,然后按回车键。 您应该得到这样的内容: 6.确保现在关闭Xcode项目。 7.通过终端,打开您的项目文件夹并打开.xcworkspace文件。 该文件是新文件; 它是在您添加任何广告连播时创建的。 8.在打开的.xcworkspace项目中,按⌘B (构建项目)。 这样就实现了项目中的Pod。 9.在ViewController.swift文件中,通过在该文件顶部键入“ import SwiftGifOrigin”来导入SwiftGif扩展名。 10.现在,在我的应用程序中,我正在使用一个生成随机名人gif的API。 在开始编写代码之前,我去了Main.Storyboard并为UIImageView(gifImageView)创建了一个插座来显示我的gif。 11.现在,我的gifImageView有一个@IBOutlet(第17行)。 凉! 在编码部分上……虽然API返回gif作为URL,所以首先我必须将URL转换为字符串(第44行)。 第二,在完成关闭时,我将gifURLString分配给gif(第27行)。 第三,我将gifImageView设置为新的gif(第29行)。 生成并运行。 魔法! 资源: SwiftGif UIImage扩展

私人vs FilePrivate

今天,我想讨论一个我多次见过但从未理解过的用法和概念的主题。 我所指的主题是私有和文件私有。 为了理解这两个主题的功能,首先我必须讨论访问控制的5个级别。 大! 让我们深入了解😎。 5级访问控制 世界上什么是访问控制? 访问控制是一项功能,可以确定源文件和模块的限制。 您可以为单个类型(类,结构和枚举)以及属性,方法,初始化程序和下标分配特定的访问级别。 有5种不同级别的访问控制,如下所示: 开放存取 公共访问 内部访问 文件专用访问 私人通道 开放访问和公共访问授予其实体在模块内所有源文件和其他模块中源文件中使用的权限。 这两个访问控制的行为非常相似,但开放访问的限制最少。 可以在所有模块和导入的模块之间子类化开放访问类。 此外,开放式访问子类可以在其自己的模块和任何导入的模块中覆盖。 通常,当您开发框架时,开放式访问将应用于API。 尽管您的界面可能是公共的,但是您可以将代码中的详细信息设置为内部,私有或文件私有。 内部访问授予其实体仅在其模块内使用的权限。 内部访问类也可以被其子类覆盖。 创建任何项目时,都必须具有访问级别。 默认情况下,内部访问被授予,因此无需明确声明访问级别。 在大多数情况下,编写单元测试时,其访问级别必须是内部的。 这很有意义,因为您只希望测试在自己的模块上执行。 在Swift 3到来之前,只有私人通道。 专用访问限制了它在声明它的源文件中的使用。 如果要创建私有类,则无法在另一个文件中访问其属性。 但是,我可以创建一个子类来覆盖超类的属性以进行访问。 我还可以使用私有访问权限来创建班级的扩展。 Swift 3到来之后,访问控制发生了一些变化。 更改之一是文件专用访问现在已替换了专用访问。 那么私人访问有什么用呢? 私有访问增加了另一层限制。 现在只能在其自己的声明(大括号内)中使用私有访问。 那为什么要改变呢? 据我所知,如果我们可以通过其他方法访问私有属性,那么私有是非常误导的,那么它真的是私有的吗? 苹果需要区别对待,因此创建了文件专用 ,而私有现在是真正的私有。 我要注意的几件事是,子类不能具有比其父类更高的访问级别(例如:您不能使用私有父类编写内部子类。这同样适用于常量,变量,属性和下标。元组必须具有相同的类型和相同的访问级别,其中一种类型的访问级别不能高于或低于另一种类型,但是对于setter和getter而言,允许setter的访问级别低于其getter。我想提及的是final关键字,由于我的好奇心和困惑,我想提及这一点。final不是访问级别,但是在任何访问级别上使用它,都可以防止子类化和覆盖。

iOS 12:Apple Presenta la nuevaversiónde su sistema操作

2018年6月4日,ApplePresentóWWDC lasúltimasnovedades para desarrolladores,entre sus nuevos productos tenemos iOS 12。 在iOS 11上使用操作系统时,通常会遇到一些问题,特别是在iOS 11上可能会出现问题,特别是在某些情况下,应该以反义词为准。 Desde el punto de vista de dessarrollo de软件,tanto Xcode como Swift han sido Actualizados,El nuevo compilador estodavíamás有效的y el nuevo SDK garantiza un renderizadomúsfluíplilas vistas de nuestras。 决赛获得最佳球员奖,埃塞俄比亚足协冠军和最佳球员奖得主。 最新消息 最终客户可以在不负责任的情况下获得一份新的书面通知,从新客户那里获得一份可兑换的原始报酬,您可以从最终客户那里获得一笔交易。 从iOS到tremodamente alto的日常使用,以及从iOS 11到11%的存储库的实际使用情况。 La tentencia se viene repitiendo cadaañoy,dadas las Expectativas,esteañovamos a estar […]

让我们停止对ViewController长度的教条

你好 我叫Ted Bendixson,我创建了其中包含200多行代码的View Controller。 我试图掩饰多年的耻辱。 你知道是怎么回事。 您参加一个聚会,发现自己与朋友和同事随意地开玩笑。 然后,您甚至没有考虑,就不小心提到了UserProfilesTableViewController的第203行。 面孔变白。 有人将酒倒入抛光的硬木地板上。 使用MVC和MVVM,您绝不应该有任何具有超过200行代码的视图控制器,对吗? 如果您使用反应性可可,则可以将这些视图控制器的尺寸缩小到更荒谬的尺寸。 那我为什么敢这样做呢? 我迷失了方向吗? 如果您像我一样,那家伙写的那个项目就遭到了一个人的折磨,后者大声地反对在多个ViewController之间传递数据的需要。 您清理了他的烂摊子,发誓永远不要让这种情况再次发生。 但是也许您对清除过去的热情太过热情了。 您的Tiny ViewController Obsession是否提高了您的生产率,还是有碍于提高生产率? 视图控制器存在的原因 在尝试回答此问题之前,我们应该首先了解ViewController试图解决的问题。 为什么我们应该首先使用具有多个视图控制器的应用程序? 通过采用这种方法,我们可以获得什么? 我曾经认识一个初级开发人员。 他不了解在控制器之间传递数据的概念。 他认为UIKit是对开发人员的一种强加手段,迫使我们创建所有这些复杂的体系结构只是为了在屏幕之间共享数据。 他更喜欢将所有代码放在一个ViewController中,因为它更易于理解。 你不能把这些东西编起来。 他只有一个ViewController拥有许多生产应用程序。 所有的UI都是用代码完成的。 要转到其他屏幕,他必须为屏幕上的一个视图设置动画,并用另一个视图替换。 在任何给定时刻,屏幕左侧或右侧都有数十个视图。 他还使用了Interface Builder,这令人困惑,因为您永远无法在他的一个ViewController中找到任何UI元素。 这是一大堆视图,按钮,表格视图和选择器,它们彼此堆叠在一起-IBOutlets相互连接在一起。 最终,他看到了光,并学会了顺其自然。 他开始使用 UIKit,而不是反对。 使用UIKit的好处 苹果公司希望我们在我们的应用程序中使用多个ViewController子类,因为这是获得UIKit原生风格的最简单方法。 如果愿意,您始终可以决定选择流氓,但您的流氓行为会付出一定的代价。 如果您决定不在您的应用程序中创建多个视图控制器,则必须开始实现UIKit免费提供的默认行为和动画。 那要花很多时间。 您也可以将初始估计值乘以10。 我们与该原生外观相关联的许多东西都直接来自UIKit。 从一个屏幕到另一个屏幕的动画,表视图,选择器,随着键盘进入屏幕而向上移动的文本字段; 全部都是UIKit。 因此,拥有ViewController这些东西的真正原因是因为我们想与UIKit一起玩得很好。 当我们与UIKit玩得很好时,我们将免费获得所有这些本机外观的行为。 换句话说,我们可以在一个月内完成一个项目,而不是十个月。 对ViewController长度有什么影响? 没有,这就是我的意思。 我们所知道的是,每个屏幕内容都需要有自己的ViewController。 没有ViewController的上帝会下雨EXC_BAD_ACCESS因为未能使该控制器低于200行而崩溃。 […]

让我们来做一些图表:iOS图表

我最近开始尝试使用iOS Charts API,并且很喜欢它。 有很多有趣的选项可用于检出图形,您可以真正自定义图形以使其完全符合所需的外观。 简单安装CocoaPods 假设您是从头开始一个新项目,请创建一个新项目并在终端中打开它 键入“ pod init ”,然后键入“ open”。 ” 打开podfile。 我喜欢在Atom中执行此操作,但是如果您没有Atom,则可以在终端中编写“ open podfile ”,然后将打开一个文本编辑器 在“ use_frameworks!”注释下写荚“ Charts / Realm” 5.从Swift 3.0的实现开始,以下代码必须粘贴在podfile的底部(在上面的第一个“结束”之下) 6.在终端“ pod install ”上运行 7. pod安装完成后,将创建以.xcworkspace结尾的项目版本。 这是包含您刚刚安装的Pod的版本。 从现在开始,您将始终在此文件中工作。 继续并从终端打开它 8.构建项目以确保一切都顺利安装。 …,让我们开始建立一些图表! ChartViewController 在深入研究特定图表的代码之前,我想在这里粘贴ChartViewController代码。 我决定将图表类型分为特定的视图,而不是在ChartViewController中编写图表的所有代码。 如果您要遵循自己的代码,我想强调两个项目: 为了填充图表视图,我使用了协议-委托关系,一旦设置了委托,该协议就会填充图表数据。 为了自定义x轴文本,我创建了一个公共类ChartFormatter,该类适用于本演示中显示的所有图表。 如果您不包括此类,则X轴文本将在图形的顶部,并且您将无法自定义字体等。 条形图。 将“图表”导入正在使用的快捷文件中。 创建BarChartView实例后,我以编程方式将图表限制在barChartSetup()中的视图边缘。 您可能会注意到barChartSetup()中还包含一个动画。 尽管我选择了.easeInBounce,但仍有多种选择可以使用; .easeInBounce刚好吸引了我。 🙂如果要签出其他选项,请删除.easeInBounce并仅输入“。”,所有其他选项将在下面填充。 最终产品: 折线图。 毫不奇怪,折线图的制作方法类似于条形图。 首先,创建LineChartView的实例,并将其约束到视图的边缘。 与条形图一样,折线图也可以设置为动画。 为了使折线图更加生动有趣,我决定添加一个渐变功能。 […]

在Swift中完善自定义断言

单元测试很棒,不是吗? 它不仅可以帮助您改进代码,而且可以确保下次更改它时不会弄乱任何东西。 测试的不利之处在于编写测试很容易,最终导致阅读困难! 在这里,我将介绍一些有用的技巧,这些技巧可以使您更容易阅读和理解单元测试代码。 断言及其使用 如果您之前没有编写过测试,则可能没有看到典型的测试断言。 断言(就像软件开发中的许多事物一样!)具有多种形状和大小,但是大多数情况下,它们是一段检查(或断言 )某些东西的代码。 if语句实际上是一个断言,在下面的示例中,我们断言该数组不为空: 如果imagesArray.isEmpty == false { //在这里做点事 } 在测试中,断言是单元测试的关键点-我们使用它们来断言 (或检查)我们的逻辑是否为我们提供了预期的结果: func testTwoMultipliedByTwoIsFour(){ 让计算器= Calculator() 让结果= Calculator.multiply(2,by:2) XCTAssertEqual(结果,4) } 在上述情况下,行XCTAssertEqual(result, 4)是断言—我们断言结果是4。 您可以在这里找到每个XCTAssert方法的完整描述。 在下面的演示中,我们可以看到样本测试失败时的外观。 您可以使用XCTFail()始终触发失败-在这种情况下,如果我们有一个if let可能无法通过,这很有用。 重要的一点是Xcode中的测试默认通过 ,因此我们必须记住在计为失败的分支上显式失败。 但是,这里的断言虽然很详细,但占用的行数却是其余测试的两倍! 让我们提取一个自定义断言以使其更具可读性。 定制断言 我们可以编写自己的自定义断言,这在断言可能变得复杂或最终导致在测试之间复制断言并实践三击规则的情况下非常有用。 我们可以提取断言,如下所示。 这使断言在测试方法本身中更小,并且还使我们对实际检查的内容有了更好的了解,而不必费力检查两个if let语句。 我们的断言现在可以正常工作。 但奇怪的是,断言失败不再显示在测试中,而是显示在我们的辅助方法中。 在运行测试时,这很烦人,因为您必须多花一些时间才能发现错误所在。 当多个测试使用相同的断言时,这确实很烦人,因为它们都在同一行上使断言失败! 我们想在调用自定义断言的地方显示失败,但是当前在我们的自定义断言的XCT函数显示失败。 幸运的是,我们可以改变这一点。 有些人会更喜欢在其自定义断言函数前加上XCT前缀,以使其看起来像内置断言方法,例如XCTAssertEquals(_,_) 。 通常不建议使用其他框架的前缀,但可以帮助您更快地在自动完成结果中找到自定义断言。 寻找最适合您的团队的东西。 更改显示断言的位置 我们有一种方法可以指出断言失败,使其看起来像来自调用自定义断言方法的位置,而不是来自其内部。 每个XCT函数都带有两个方便的默认参数-用于指示将红叉放在Xcode中的位置以及在哪里显示错误消息。 它们是file和line ,并且有两个对应的特殊“宏” […]

使用结果扩展编写声明性代码

最近,我读了Benedikt Terhechte的精彩文章,他在其中扩展了optionals的API。 在标准银行,我们非常广泛地使用结果类型,因此我采用了相同的想法并将其应用于结果类型。 在这篇文章之后,我们将获得可组合的代码和声明性的API,类似于下面的代码片段。 您可以在以下Playground文件中找到一个工作示例。 TYRONEMICHAEL /结果扩展 result-extensions –使用结果扩展 github.com 编写声明性代码 虚构的摘要 假设我们正在为客户构建一个简单的应用程序。 与域名专家坐在一起后,他通知我们任何人都可以浏览该应用程序,但是要成为注册用户,您需要满足以下要求: 注册用户必须具有有效的 标识符 。 注册用户必须具有有效的电子邮件地址,并且该电子邮件地址必须是Gmail地址。 注册用户必须是千禧一代或X一代 。 我们需要向用户展示为什么尝试后无法注册 。 用应用程序扩展结果类型 要求之一是向用户显示为什么他们不能成为注册用户。 通过使用应用程序,我们可以非常漂亮地实现这一目标。 在编写我们的应用程序之前,我们需要定义一个称为半组的协议。 布兰登·威廉姆斯(Brandon Williams)对半群是什么以及为什么要使用半群有很好的解释。 出于本文的目的,我们只需要一个Array即可符合协议。 现在,我们可以编写扩展结果类型的应用程序。 这允许编写以下代码。 如果在上面打印用户对象的内容,将得到以下内容: 失败:3个要素 -“无效的ID” – “不合规电邮” -“无效的千禧一代” 斯蒂芬·塞利斯(Stephen Celis)的精彩视频详细介绍了上述应用程序和Swift。 一块很棒的手表。 用AND扩展结果类型 要求之一是用户必须具有有效的电子邮件地址和有效的Gmail地址。 让我们使用和的以下代码扩展结果类型。 现在,我们可以执行以下操作。 如果打印结果,将得到以下输出。 失败:1个元素 -“无效的Gmail地址” 用OR扩展结果类型 最后一个要求是用户是千禧一代或X代。我们可以通过使用or扩展结果类型来满足此要求。 现在我们有以下内容。 如果打印结果,将得到以下输出。 失败:2个要素 -“无效的千禧一代” -“无效的gen x” […]

演示控件,自定义视图和更轻巧的UIViewControllers(第2部分)

现在我们有了MVVM,MVP,VIPER,VIP,但是其他部分呢? 复杂的UI逻辑应该放在哪里? 在上一篇文章中,我介绍了一种拆分UIViewController的方法,以使UITableViews和UICollectionViews由我称为TableViewDriver或CollectionViewDriver的新组件驱动。 这次,我将进一步从您的项目的显示方式中抽象出UIViewController,因此从视图控制器中,您将无法确定是使用UITableView,UICollectionView还是UIStackView来显示项目。随你。 在这篇文章中,我将向您介绍一种非常强大的技术: 演示控件。 Presentation Controls假定您通过使用情节提要板或xibs使用“界面构建器”,因为它们是以这种方式创建的。 问题 使用表视图驱动程序,您的代码将变得更加整洁,但是视图控制器仍然具有许多IBOutlet成员,这使得驱动程序有点像根本问题的解决方法。 根本问题是UIViewController是表示逻辑的核心。 它非常了解其成员以及他们如何显示数据。 如果不修改视图控制器的代码,就无法修改数据的显示方式。 演示控件 表示控件是一个对象,负责处理视图控制器表示逻辑的一小部分。 它可以具有IBOutlet,并且可以作为IBOutlet包含在视图控制器中。 它们非常强大,可以从低级表示逻辑中抽象视图控制器,使其成为其管理的表示控件的协调器。 计划 使用表示控件将简化视图控制器,该控件将负责处理表示细节,并将通过IBOutlet包含在视图控制器中。 解决方案 界面生成器是该技术的重要组成部分。 如果您没有注意到这一点,则可以使用Interface Builder将对象添加到视图控制器。 该对象小部件将代表我们解决方案中的Presentation Control。 因此,要使用Presentation Controls,您要做的第一件事就是使用Interface builder将新的Object添加到视图控制器中: 该对象将是NSObject的子类。 因此,这里我们必须创建一个新的NSObject子类,将其称为{Whatever} PresentationControl,并将其分配给最近添加的对象。 请注意,现在我们已将对象分配给场景,当您使用界面生成器自动查找对应对象时,将显示一个新选项: 现在我们已经在场景中有了演示文稿控件,我们可以将IBOutlet连接到它了,就像我们用来将IBOutlet连接到UIViewController子类一样: 最后,可以通过IBOutlet将此Presentation Control连接到视图控制器: 结论 一旦有了表示控件来处理视图的一部分,视图控制器就将无法确定数据的实际显示方式,这很棒。 但是,强大的力量伴随着巨大的责任。 这不是灵丹妙药,您必须在选择所有替代方案之前对其进行评估。 例如,您可以使用子视图控制器或自定义视图拆分UIViewControllers。 我个人发现这非常方便且有用,它使我的视图控制器比以往任何时候都更薄。 如果您以其他方式执行此操作,我将很高兴听到它。 请在下方留下你的意见! 谢谢!

使用Apple Watch进行24/7加速度计跟踪

watchOS的人机界面指南 WatchKit编程指南 WWDC 2016 —设计出色的Apple Watch体验 WWDC 2016 — watchOS的新增功能 1.苹果框架:构建基块 1.1后台任务 WWDC 2016 —使您的手表应用程序保持最新 WWDC 2016 — watchOS上的性能架构 watchOS上的应用生命周期 watchOS上应用程序的默认状态not running 。 正在前台运行且屏幕打开的应用程序正在running 。 Dock中的应用程序和活动表面上具有复杂功能的应用程序处于suspended状态,已加载到内存中,可以快速恢复。 运行时未在监视屏幕上显示的应用程序(无论屏幕关闭还是其他应用程序或表面在前景中)都处于background状态,这是严格预算的, 实际上是我们的目标。 Apple提供了四个后台任务选项,watchOS可以将它们传递给扩展委托的handle(_ backgroundTasks: Set)方法: WKApplicationRefreshBackgroundTask是一种常规的后台任务类型,不适用于特定的刷新类型。 这种类型最常见的用例是安排其他任务。 在我们的应用程序中,它用于触发几乎所有工作:从CoreMotion请求加速度计数据,将其写入文件,然后开始将文件传输到手机端。 为了从watchOS接收此类任务,您应隐式请求它。 WKSnapshotRefreshBackgroundTask是一种任务类型,专门用于您的应用程序需要更新其快照(用作启动映像,如Dock中所示)时。 WatchOS会不时将任务分配给Dock中的每个应用程序,但也可以提出要求。 WKWatchConnectivityRefreshBackgroundTask是一种任务类型,用于当您通过WatchConnectivity框架将数据从iPhone传输到手表时。 我们目前不使用它。 WKURLSessionRefreshBackgroundTask是后台联网任务完成后分配给扩展委托的任务类型。 我们目前还没有使用它。 为了请求WKApplicationRefreshBackgroundTask : 2.1.3 SendSamplesOperationQueue SendSamplesOperationQueue责任是SendSamplesOperationQueue的创建和排队。 它跟踪成功和失败的操作,为将要选择的时间块重新填充新操作,具有自己的状态以防止使用外部的精确操作种类进行重新填充(例如,在ShortTasks中,我们希望允许从传感器请求数据只能在前4秒​​钟内执行操作,但只要我们没有任何限制,就可以创建以前准备发送的文件)。 将按以下优先级选择新操作的时间块: 如果连续尝试的次数少于numberOfRetriesIfFailedToSend ,则先前使用的时间戳和先前的文件传输失败。 如果队列的阶段允许,则使用以前使用的时间戳,但不准备发送文件(这意味着该应用在准备文件时被终止)。 如果队列的阶段允许,则将新时间戳计算为最新的先前时间戳+块持续时间 ,如果该时间早于块持续时间 ,则在其他情况下,将不会创建操作并且自我填充将停止,最后执行performWhenEverythingTransferred关闭。 2.1.4数据文件 […]

Plank简介:iOS的不可变模型生成

Rahul Malik | Pinterest技术主管,iOS核心体验 去年,我们的iOS团队全面改革了整个应用程序的体系结构。 这是一项巨大的努力,导致开发人员可以更快地迭代应用程序,更易于扩展,而全球Pinners的应用程序则快3倍。 我们的新系统严重依赖于并发。 UI渲染,图像下载,GIF解码和网络响应处理只是利用多个线程来提高性能的一些领域。 这意味着这些组件使用的对象必须是线程安全的,以避免错误和潜在的崩溃。 由于模型对象几乎遍历我们应用程序的所有组件,因此确保模型层可以安全地跨线程使用非常重要。 为了解决这个问题,我们转到了一个不变的模型层。 不可变对象与可变对象的不同之处在于,一旦创建它们就无法对其进行修改,这从本质上使它们成为线程安全的。 这使开发人员可以编写更易于推理的代码,因为一旦建立不变量就无法更改。 今天,我们是开放源代码的Plank,这是我们为实现此目的而创建的iOS不可变模型生成器。 Plank是用Swift编写的命令行工具,可生成不可变的Objective-C模型。 在本文中,我们将重点介绍一些主要功能以及其创建的动机。 动机 设计和维护模型层可能很繁琐且容易出错。 缺少简单的null检查或尝试序列化包含无法序列化的属性的对象可能会导致未定义的行为和崩溃。 手写模型还可能遭受其实现中的不一致问题,并且在序列化时可能导致不同的行为和策略。 以下是一些由于手写模型问题导致的常见错误和崩溃的示例。 通过Plank生成模型 让我们用这些字段创建一个表示Pin的模型。 定义架构 Plank将模式文件作为输入,因此我们需要创建一个。 这是Pin类型的架构。 您会注意到我们指定了模型的名称及其属性列表。 请注意,该链接指定了一个附加的format属性,该属性指示Plank使用更具体的类型,例如NSURL或NSDate 。 产生模型 假设此架构另存为pin.json我们通过运行plank pin.json生成模型。 下面,我们将重点介绍Plank从您的模式生成的一些功能。 $木板pin.json Plank创建的Pin类接口 您会注意到的第一件事是所有属性都是readonly 。 这使该类不可变,但是它并没有真正的用处,因为我们没有办法用任何值填充Pin的实例。 为了解决这个问题,我们需要一个抽象,它将采用一组值并产生一个不可变的对象。 变异和建造者 通过生成器类执行Plank生成的模型中的变异。 这是构建器模式的直接实现,Plank会为您生成它。 builder类是一个单独的类型,其中包含readwrite属性和一个将创建新对象的build方法。 JSON解析 现在,我们有了一个不可变的模型和一个构建器类来创建新实例。 但是,大多数应用程序不是静态的,并且依赖于从API返回的JSON数据。 这是我们的Pin模型的示例JSON响应。 为了正确处理此响应,我们不仅需要断言响应类型是正确的,而且还需要添加其他逻辑以将链接表示为NSURL的实例。 小心处理null值也很重要,以避免将属性设置为NSNull值或将null传递给需要nonnull参数的API。 这些错误可能导致无法预测的行为和崩溃。 Plank将创建一个名为initWithModelDictionary的初始化方法,该方法处理解析符合您的模式的NSDictionary对象。 序列化 如果要为应用程序建立脱机支持或在应用程序启动期间保留数据,则需要将模型存储到磁盘。 iOS上最常规的解决方法是在每个模型上实现NSSecureCoding 。 […]