Tag: swift

简短有趣:添加音频

Apple通过AVFoundation使向应用程序添加音频相对容易,该框架允许您创建和/或向应用程序添加音频或视频。 AVAudioPlayer类的实例称为音频播放器,可播放文件或内存中的音频数据。 我制作了一个简单的应用程序,主要使用AVAudioPlayer来练习和演示如何在您的应用程序中实现音频,根据我的经验,这里的三个步骤有望帮助您在应用程序中实现音频。 第一步:导入AVFoundation框架 在项目浏览器中,选择您的项目名称。 在“内容区域”中,在“目标”下选择项目的名称,然后单击“构建阶段”。展开“将二进制文件与库链接”,然后单击“ +”按钮添加“ AVFoundation.framework”。 第二步:将AVFoundation导入文件 就像在文件顶部输入“ import AVFoundation”一样简单 第三步:实例化和编码 AVAudioPlayer是一个类,因此您必须实例化它。 为了获取音频文件,必须创建一个URL。 文件的路径在包中(可帮助您访问包目录中的代码和资源),在该目录中您将插入音频文件的名称。 您在“ pathForResource”的参数中插入文件名(不包括其音频类型,将其保存为“类型”)。 就是这样! 添加简短而甜美的音频很有趣,因此我建议您尝试一下。

如何制作Pokemon Go for iOS —第1部分:地图和位置

在本系列文章中,我们将借助Swift 3为iOS编写一个简单的’Pokemon Go’克隆。如果您使用的是Swift的当前公共版本,则可能要考虑使用Xcode 8,它带来了Swift 2.3和Swift 3。 如果值得使用Swift 3,则可以在这里了解。 不要犹豫,使用旧版本的Swift来完成本教程,您当然可以! 如果您没有上述工具,则可以考虑从AppStore下载Xcode。 这样,您便可以开始使用Swift 2(撰写本文时)。 因此,首先让我们启动Xcode-beta(Xcode 8)并创建一个新项目。 我们要创建一个单一视图应用程序,因为我们要从一个普通的白色项目开始。 然后输入项目名称,在这种情况下将是pokemongo。 您可以随意命名,因为稍后将显示实​​际的名称。 我们要使用的语言显然是Swift ,而不是Objective-C。 对于设备,您可以选择自己喜欢的任何东西,仅iPhone或iPad,或两者都通用。 在单击下一步之前,请不要忘记选中“ 使用核心数据” ,我们需要它来将数据存储在手机上。 单击下一步后,将显示您的项目摘要。 将显示名称更改为“ Pokemon Go”,并将部署目标更改为您选择的版本,在我的情况下为10.0,因为Swift 3仅在iOS 10上运行。此外,请取消选中除Portrait之外的所有其他设备方向 。 我们几乎都准备出发。 最后一步是转到窗口左侧的文件浏览器中的 ViewController.swift ,并删除所有不必要的注释和函数,因为这将清理我们的代码(好的代码仅具有必要的功能!) 现在我们已经准备就绪,可以从实际项目开始。 转到Main.storyboard ,然后在右侧区域的最低框中选择第三个图标,然后搜索Map Kit View 。 将其拖放到您的项目中并调整其大小。 仍然在选择“地图视图”的情况下,单击画布底部灯条右侧的倒数第二个项目,可以在其中找到已拖动了地图视图的视图控制器。 确保未选择“约束到边距”并将其(如果尚未设置),所有约束都设置为0。最后,点击底部的“添加约束”,从现在开始,我们的画布将适应所有屏幕尺寸。 现在,我们想使用代码访问“地图视图”,因此需要创建一个出口。 因此,我们必须单击右上角带有两个相互干扰的圆圈的图标。 您应该会看到第二个窗口,其中包含我们的视图控制器的代码。 现在,在代码画布中的viewDidLoad-function和ViewController类之间 ,按住控件并从Map View中拖放。 要输入名称,请输入mapView (Swift主要使用驼峰式大小写,这意味着您从小字开始,每当一个单词被一个空格隔开时,您只需将“新”单词的首字母大写)。 完成所有这些之后,单击右上角的左对齐图标,然后选择ViewController.swift文件。 您应该在mapView出口旁边找到一个警告图标。 这是因为尚未导入框架 (功能等的集合)。 […]

输入安全网络层2.0

有很多关于使用Swift以安全类型进行网络层的文章。 无论使用哪种网络API,这些方法都依赖于返回正是我们期望的数据类型。 这个想法是利用Swift的类型推断/泛型能力来避免强制转换返回的类型。 在这篇文章中,我们将通过强耦合我们要获取的端点和它必须返回的数据类型来尝试进一步发展。 快速提醒 假设我们要获取“ dog.ceo ”端点之一。 通常从定义路线开始。 枚举对此非常有用: 让我们尝试滥用这种机制:在仍然使用相同端点的同时,我们尝试明确告诉编译器结果是“ Result ”。 如预期的那样,失败fails。 我们确实拥有一个编译时类型的安全网络层😏,并对我们的API进行了少量更改。 很酷。 感谢您的阅读,并随时提供反馈! 敬请关注。

Swift数组vs ContiguousArray

我们都每天使用数组。 但是我们是否考虑过有效使用它们? 在这里,我将讨论一种技术,通过该技术,我们可以基于其中的Element改善数组的性能。 数组–理想元素 尝试在数组中使用值类型。 使用值类型时,优化器可以消除Array中大部分的开销,这些开销是处理数组支持NSArray的可能性所必需的。 通过使用没有引用类型的值类型,可以避免额外的保留,释放Array内部的流量。 但是要小心并考虑在使用大值类型与引用类型之间进行权衡。 您可以在此处了解更多信息。 ContiguousArray ContiguousArray类型是一种特殊的数组,始终将其元素存储在内存的连续区域中。 如果数组的Element类型是类或@objc协议,并且您不需要将数组桥接到NSArray或将数组传递给Objective-C API,则使用ContiguousArray可能比Array效率更高,并且具有可预测的性能。 如果数组的Element类型是结构或枚举,则Array和ContiguousArray的效率应相似。 考虑以下课程。 班级地址{ var street =“” var city =“” var state =“”; 枚举AddressAttributes { 凯斯街 凯斯城 案件状态 } func updateAttribute(值:字符串,属性:AddressAttributes){ 开关属性{ case.Street: 街道=价值; 案例城市: 城市=价值; 大小写 状态=值; } } } 我测量了将此类对象添加到Array和ContiguousArray所需的平均时间。 我采用了一个任意值(1000000),只是为了演示如何在更大范围内表现不同。 func testPerformanceForClassArray(){ 让地址=地址() var数组:[地址] = [] 自我衡量{ for _ in […]

Swift并行编程—第1/4部分

并发,并行和调度队列 每当我们听到并行编程时,就会想到两个令人困惑的术语:并发和并行。 首先让我们看看现实生活中的角色: 并发性:我们的日常工作涉及多任务处理。 很多时候,我们执行多任务处理,但最终会同时完成一个任务,但是理想情况下,这就是上下文切换。 它也有一些限制。 假设我们每天有100项工作,但不能将其增加到1000项。 并行性:如果我们可以得到更多的物理东西,那么可以同时完成两个或更多的工作。 如果我有4臂,那么这篇文章可以在一半的时间内完成。 让我们来看看计算机世界中的两个术语: 并发: 并发意味着应用程序同时(并发)在一项以上的任务上取得进展。 如果计算机只有一个CPU,则该应用程序可能无法完全同时执行一项以上的任务,但是一次要在应用程序内部处理一项以上的任务。 在开始下一项任务之前,它并没有完全完成一项任务。 当我们谈论至少两个或更多任务时,并发本质上是适用的。 当一个应用程序几乎可以同时执行两个任务时,我们称其为并发应用程序。 尽管这里的任务看起来像是同时运行的,但实际上它们可能并非如此。 它们利用了操作系统的CPU时间分片功能,其中每个任务运行其任务的一部分,然后进入等待状态。 当第一个任务处于等待状态时,CPU被分配第二个任务以完成其部分任务。 操作系统根据任务的优先级工作,因此分配CPU和其他计算资源,例如内存; 依次处理所有任务,并给他们完成任务的机会。 对于最终用户,似乎所有任务都是并行运行的。 并发复杂度 假设有5个朋友搬进了房子,每个人都有一张床。 哪种更复杂的方式来构造它? 5人同时组装一张床或 每个人组装自己的床 想一想如何为几个朋友编写有关如何将床组装在一起的说明,而无需彼此扶持或等待工具。 他们需要在正确的时间协调动作,以将床的各个部分组装成成品床。 这些指令真的很复杂,很难编写,也可能很难阅读。 每个人都自己建造床时,说明非常简单,无需等待其他人完成操作或使用工具即可。 罗伯·派克 ( Rob Pike)有一个关于 并发不是并行的演讲。 平行性 并行不需要两个任务存在。 通过为每个任务或子任务分配一个内核,它可以使用CPU的多核基础结构同时运行部分任务或多个任务。 并行性本质上要求具有多个处理单元的硬件。 在单核CPU中,您可能会获得并发性,但不能获得并行性。 并发是独立执行的进程的组成,而并行性是计算的同时执行。 并行性是指应用程序将其任务分解为较小的子任务,这些子任务可以并行处理,例如在多个CPU上同时进行。 并发是一次处理很多事情,更多的是关注结构。 并行性是一次执行很多事情,其重点是执行。 一个应用程序可以是并发的,但不能是并行的,这意味着它可以同时处理一个以上的任务,但是两个任务不能同时执行。 一个应用程序可以是并行的,但不能是并行的,这意味着它可以同时处理多核CPU中一个任务的多个子任务。 应用程序既不能是并行的,也不能是并发的,这意味着它一次顺序地处理所有任务。 一个应用程序可以是并行的,也可以是并发的,这意味着它可以同时在多核CPU中同时处理多个任务。 自从出现以来,CPU技术的最大改进之一就是能够包含多个内核,因此可以运行多个线程,这意味着在任何给定时刻可以执行多个任务。 在iOS中,有两种实现并发的方法:Grand Central Dispatch和OperationQueue。 这两个主题都很广泛,因此我将本文分为四个部分 : […]

自动布局:朋友还是敌人?

首先是第一件事。 根据Apple的自动版面配置: 根据放置在视图上的约束,动态计算视图层次结构中所有视图的大小和位置。 例如,您可以限制按钮的位置,使其在“图像”视图中水平居中,并且按钮的顶部边缘始终保持在图像底部下方8个点。 如果图像视图的大小或位置发生更改,则按钮的位置会自动调整以匹配。 这种基于约束的设计方法使您可以构建可动态响应内部和外部更改的用户界面。 这是一个非常强大的工具,当有人完全理解它时,这几乎是魔术。 如此说来,下面列出的是我多年来发现的一些优点。 它可以帮助新开发人员 2年前,作为新开发人员,我不得不学习Swift,如何正确编写语言以及诸如扩展,闭包之类的许多其他内容。 我不想花更多的时间来编写UI,所以我了解了自动布局的工作原理。 我了解到,如果新开发人员能够很好地理解该技术,则可以节省大量开发时间。 简单的布局和适应性 当涉及到简单的布局和应用程序的适应性时,“自动布局”是一个很好的工具。 特别是对于Xcode 8,界面构建器背后的团队在改善它方面做得非常出色。 确实很棒,并且具有一些很棒的功能(接口构建器的提示和技巧将在第二部分中介绍,请继续关注) “自动布局”比编写UI更快 在iOS开发中创建用户界面的方法不是对是错。 对于许多用户而言,“自动版式”的工作原理比另一种更好且更快。 我就是其中之一。 我认为使用自动布局比通过编程设置约束要快。 先进的技术 信不信由你,Auto Layout是一项先进的技术,Apple付出了大量的努力来改进它并使其变得更好。 通过每次Xcode更新,我发现Interface Builder团队所做的更新确实执行得很好。 有用的结论 作为开发人员,在Xcode上设计UI时不要只放弃/使用一种方法。 两种方法都有其优点和缺点。 拥抱他们两个。 如果您是Auto Layout的新手,则WWDC讲座是了解其工作原理并了解一些有用的见解的良好起点。 更具体地说,当我开始尝试“自动布局”时,WWDC对我来说是如此。

贴在屏幕底部的视图

今天,我们将看到如何将视图固定在屏幕底部。我们使用自动布局的程序化方法。 首先,我们创建带有一些文本的标签,例如“离线模式”。然后,将其放置在屏幕底部。 var lblOffline = UILabel() 然后在viewDidLoad()方法中,将视图添加到屏幕底部。 fileprivate func setupName(){ 令高度= CGFloat(50) //设置标签属性 lblOffline.text =“离线模式” lblOffline.backgroundColor = .red lblOffline.textAlignment = .center //步骤1 lblOffline.translatesAutoresizingMaskIntoConstraints = false //第2步 view.addSubview(lblOffline) //步骤3 NSLayoutConstraint.activate([ lblOffline.leadingAnchor.constraint(equalTo:view.safeAreaLayoutGuide.leadingAnchor), lblOffline.trailingAnchor.constraint(equalTo:view.safeAreaLayoutGuide.trailingAnchor), lblOffline.topAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor,常数:-height), lblOffline.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor), ]) } 就是这样做的。 谢谢阅读。 请感觉是否有任何疑问。 如果您喜欢这个,请鼓掌并支持我。

Firebase:用户注册,登录和数据管理

努力在Firebase上创建新用户? 是否对将多个元素保存到Firebase上的特定用户感到困惑? 不要再看了! 请按照以下步骤操作,您将可以很好地在Firebase上填充用户群。 如果您尚未在项目中设置Firebase,请查看Will的博客以获取指导。 设置用户授权和数据库规则: 转到您正在处理的项目的Firebase控制台,然后转到Authentication(位于Firebase左侧“开发”下)。 导航到“登录方法”,您将在其中看到每种用户登录方法的默认状态均已禁用。 在本教程中,我将仅启用“电子邮件/密码”,尽管在Stack Overflow上使用Google / Facebook等登录用户方面有很多建议。 继续,然后单击将鼠标悬停在“电子邮件/密码”上并将状态切换为“启用”时显示的铅笔图标。 大! 接下来转到“数据库”,位于Firebase左侧“身份验证”下。 导航到“规则”。您将看到Firebase写入了默认规则(也在下面显示)。 当前,这些规则说的是“如果存在授权用户,则您可以读取保存的数据并将更多信息添加到保存的数据中。” 如果要创建特定于用户的组,则必须添加特定于该组的规则。 仅供参考-Firebase将任何组称为“子级”。您的数据库规则应类似于以下所示。 是时候开始使用XCode来开始执行代码了。 用户注册: 除了UIKit,还将Firebase,FirebaseDatabase和FirebaseAuth导入到Swift Cocoa Touch Class文件中。 如果您不这样做,则XCode将无法识别您将要调用的Firebase函数。 您将需要三个UI项:1)电子邮件的文本字段,2)密码的文本字段,和3)名为“ Sign-Up”的按钮,该按钮作为一个操作从情节提要链接到Swift Cocoa Touch Class文件。 在按钮的动作功能中,我们将编写相关代码。 首先,创建一个与它们各自的文本字段相等的电子邮件和密码属性。 由于文本字段本质上是可选的,因此我选择在guard let语句中解包文本字段。 接下来,检查以确保电子邮件和密码文本字段不为空。 如果它们不为空,则可以调用FirebaseAuth的createUser(withEmail :)方法。 上面的代码中需要注意的几件事-首先,您将看到一个名为“ ref”的属性,该属性等于FIRDatabase.database()。reference()的实例。 为了将数据读取或写入数据库,必须创建参考数据库的实例。 末尾的“根”表示参考的“根位置”。 由于我想将新用户添加到我先前创建的“用户”子级中,因此我在createUser(withEmail :)方法完成时对其进行调用。 在这个孩子中,我创建了一个新的“用户”孩子,其值设置为电子邮件。 尝试运行您的应用,然后单击“注册”按钮; 输入电子邮件和密码后,转到Firebase项目控制台并单击“数据库”,您将看到与以下内容类似的内容。 用户登录: 登录用户的代码与注册用户的代码非常相似。 从下面的屏幕快照中可以看到,注册用户和登录用户之间的主要区别是FirebaseAuth方法。 如果是登录用户,则应使用FirebaseAuth的signIn(withEmail :)方法。 向用户添加数据: 现在玩的开心! 在我的示例中,我正在创建一个由用户组成的“收藏夹”部分。 […]

使用Realm.io保持Swift枚举

Swift枚举是将语义赋予非自解释属性的好方法。 如果使用得当,它们为我们提供了更具可读性的代码库,以及一种无需查看文档即可快速选择正确值的方法。 你更喜欢哪个? 后者立即讲述了整个故事,不是吗? 但是,由于它是一个自定义枚举,而不是原子类型,因此Realm无法立即存储它。 但是不要担心,这很容易解决! 如何使用Realm存储枚举 这里的想法是为我们的枚举提供自定义的getter和setter方法,并将原子表示形式存储在Realm中。 这是我们的示例枚举,它枚举了所有任务类型: 现在,由于我们无法将TaskType对象存储在Realm存储区中,因此我们必须存储某种标识符,以后可以将其转换为枚举表示形式。 TaskType方便地是Int的枚举,这意味着我们可以只存储其rawValue 。 但是,如果我们拥有Realm不支持的类型的枚举(例如UInt ),则我们可以选择存储枚举值的索引或为每个枚举分配一个可以存储的标识符。 为了存储表示,我们将创建一个私有变量,该变量将包含标识符和一个公共变量(Realm不会尝试持久化),以及一组访问器,以使用持久化变量进行相应的操作。 如您所见,我们将与Realm兼容的privateType保留为私有,以确保我们使用支持枚举的type变量。 为type变量定义的getter和setter负责将存储的标识符转换为我们的枚举,反之亦然。

鸡问题(面向协议的编程)

大家好 在本文上,我们来讨论协议扩展和面向协议的编程(POP)。 关于这个主题有很多讨论,Swift协议扩展和多重继承之间有很多比较。 因此,让我们讨论两者之间的区别以及POP听起来为什么更可靠的原因。 鸡问题 我喜欢用这个例子来说明一个小问题如何变成大规模开发和实际应用。 首先让我们看一下问题,然后再讨论。 想象一下我们需要构造鸟类的“对象/实体”的应用程序。 乍一看,我们将拥有Perrots,Sparrows和Falcons。 现在,让我们为此创建一个漂亮而智能的代码。 OOP和多重继承 所有这些鸟类共享许多东西,例如“喙”,“羽毛”,并且它们都可以“飞行”。 因此,让我们考虑以下Birds App的体系结构。 看起来很棒! 在这一点上,我们作为开发人员对我们的创作感到非常自豪。 它干净,可靠,我们只编写了一次代码,只是“ fly”方法的一种实现,这是一种非常复杂的算法。 现在,我们制作了该产品的版本1 。 此时,客户(Bird应用程序的所有者)说:“嘿,您知道吗,我注意到我的客户也希望拥有Chicken,所以请向此应用程序中添加Chickens,一旦您将它变得非常简单告诉我您有一个非常灵活的体系结构与OOP一起使用” 好的,这很容易……鸡是鸟,所以它将成为鸟的一个子类……但是等等……鸡不能飞! 因此,在这一点上,我是否需要重写此“ fly()”方法,并从“ Bird”中取消我所有漂亮的算法? 等等,这样做不仅是在重写代码,但是如果我心爱的客户决定明天他将发明一种新型的能飞的超级鸡肉,我该怎么办? 将“鸡”否定为“ fly()”的新“鸡”子类? 如果我的客户决定将应用程序移至南极并创建企鹅? 企鹅没有羽毛! OMG…我刚刚意识到我的整个体系结构对我的客户来说不够灵活! 我应该改变它吗? 我应该重写我的整个应用程序吗? 提出V2? 我应该更换我的客户吗? 我是否应该换一个鸟类完美的星球,它们都具有相同的特征? 好吧好吧让我们冷静一下 让我们尝试考虑可能的解决方案,毕竟,OOP很棒,并且确实可以反映现实世界的复杂性。 好吧,不完全是。 我们可以尝试使用OOP解决方案来奋斗。 我不会深入探讨我们可以尝试的失败解决方案: 创建两个基类:“鸟”和“飞鸟”(失败:如果客户决定购买飞机怎么办?) 使用协议/接口定义飞行方法(失败:重写很多代码) 将“ fly()”定义为接收可以飞行的对象的静态方法(失败:如果我有数百万个飞行对象怎么办?并发,多线程) 我与数百名不同的开发人员进行了此练习,让他们尝试许多解决方案。 简而言之,在OOP中解决此问题的唯一可能解决方案是使用多重继承,但是众所周知,这很危险。 只有很少的编程语言允许这种功能,并且在其自身的实现中有许多警告。 Pearl和Python使用一个有序列表进行多重继承,Java 8尝试使用编译器来避免错误,C ++实际上是真正在其完整扩展中真正实现多重继承的唯一语言之一。 因此,如果您不想仅在应用程序中创建C ++模块来解决该问题,就让我们现在尝试使用Swift功能来解决Chicken Chicken问题。 Swift […]