Tag: 编程

快速提示:懒惰序列

SequenceType和CollectionType具有一个很酷的名为lazy属性。 Apple将lazy定义为:“一个包含与该序列相同的元素的序列,但是在其上懒惰地实现了某些操作,例如map和filter 。” 最好用一个例子来说明。 假设我们有以下代码: //创建一个包含1到1,000的数字的数组。 变数= [Int]() 数字+ = 1…1_000 让newNumbers =数字 .filter {$ 0%2!= 0} //已执行1,000次 .map {$ 0 * 10} //执行500次 打印(“ \(newNumbers.last)”) 如果要访问newNumbers的最后一个元素或任何元素,则必须执行构建newNumbers数组所需的每一个计算。 那是`filter`的1000次迭代,而map另外500次。 现在,更懒惰的: //创建一个包含1到1,000的数字的数组。 变数= [Int]() 数字+ = 1…1_000 让newNumbers = numbers.lazy .filter {$ 0%2!= 0} //仅执行3次 .map {$ 0 * 10} //仅执行1次 打印(“ \(newNumbers.last)”) 这次,我们只完成了filter三个迭代,以及map一个迭代。 因为我们使用了lazy序列属性,所以实际上返回了一个新类型( LazyMapBidirectionalCollection ),而不是简单的数组。 […]

PhotoKit的迷你教程

我正在创建一个简短的教程,说明如何从照片库中获取图像并将其显示在故事板上。 这将要求用户许可,然后自动显示图像。 本教程将从库中获取第一张图像并显示它。 我们将使用PhotoKit ,有关更多信息,请阅读Apple指南。 我们首先创建一个名为loadImage的新方法,该方法将返回可选的UIImage 。 我们将使用此方法来抓取图像以显示在屏幕上。 将其设为可选,以防万一我们无法从照片库中获取任何图像。 创建一个用于获取照片资产的管理器对象。 PHImageManager会缓存资产图片,从而使我们重新请求的资产能够更快地加载。 默认方法返回管理器对象。 接下来,创建类型为PHFetchResult的fetchResult 。 此类为我们提供了从Photos fetch方法返回的资产的有序列表。 PHAsset实例表示我们将检索的图像。 fetchAssets方法将检索图像。 选项使我们可以对获取的资产进行过滤和排序,而fetchOptions是接下来要创建的方法。 我们实例化PHFetchOptions类。 此类将使我们能够从获取的资产中过滤,排序和管理结果。 sortDescriptors属性指定获取的对象的顺序。 我们将使用一组键路径和排序顺序来使用NSSortDescriptor数组。 我们将使用creationDate键根据资产的创建日期对资产进行排序。 您可以在此处了解有关关键路径的更多信息。 请求选项方法将返回PHImageRequestOptions 。 我们将使用此方法来影响图像的传递方式。 我们将isSynchronous的布尔值设置为true。 此属性使我们可以设置图像的质量或获取请求的传递速度。 我们返回requestOptions ,我们将在loadImage()方法中使用此方法。 让我们回到我们的loadImage方法并添加以下代码: 我们将创建一个可选图像,并在没有功能的情况下返回该属性。 使用requestImage查找指定的资产。 我们将使用之前创建的fetchResult对象通过使用object(at :)方法来获取特定索引处的资产。 我们还指定了图像尺寸和内容模式,该模式告诉我们如何使图像适合请求尺寸的宽高比。 我们将创建的requestOptions()方法传递给options参数。 这说明了我们的请求将如何处理。 创建一个保护声明,以确保我们的img不为空,否则我们只将图像返回nil。 然后,我们将最终返回我们的形象。 接下来,在情节提要中。 将ImageView添加到View Controller中,然后将插座连接到您的swift文件。 @IBOutlet弱var imageView:UIImageView! 现在,我们将创建一个处理用户权限的photoAuthorization方法。 此方法将检查用户是否向我们授予了访问照片库的权限,如果获得我们的授权,我们将运行其余方法。 如果没有,我们将只打印一份声明。 如果愿意,可以使用UIAlertController提示警报消息。 这会检查我们当前的授权状态。 PHPhotoLibrary对象代表“照片”应用程序管理的整个资产集。 switch语句用于检查我们的状态并确定我们应该做什么。 如果身份验证成功,我们将使用loadImage方法将图像返回到imageView出口。 […]

Swift编程入门第12部分-类型别名,属性观察器以及Self与self

之前,我们谈论过中央车站的调度和关闭。 入门Swift编程第11部分-大型中央调度和关闭 以前,我们了解了代码结构,可读性和其他一些原理。 medium.com 这是一个艰难的过程,但您会很高兴知道所有困难的事情都已经过去了。 本文将介绍一些新概念,以帮助您提高代码的可读性,简化代码,并在Self与self领域中提供一些背景,而不是大写S 类型别名有助于使我们的代码更具可读性,并使我们作为开发人员的生活更加可忍受。 您可能会理解这在其他语言中被称为alias或typedef ,但是在Swift中我们使用typealias 。 Typealias只是将类型重命名为更易于使用或理解的名称。 在代码中,您可以使用typealias来获取原始类型并将其重命名为更适合您的上下文的名称。 让我们看一个例子: 接下来,属性观察器很不错,因为它们可以帮助您自动执行每次变量更新时需要发生的某些事情。 财产观察员基本上观察财产的变化。 它们有两种形式。 willSet —在设置变量之前执行操作 didSet —设置变量后执行操作 我几乎从未使用过willSet ,但是我didSet都在使用didSet 。 属性观察器适合您的代码,如下所示: 是,有一点不同! 即使看起来很细微,差异也很大。 在类和结构中,有时我们必须从该实体拥有的方法中引用该实体的属性。 在这种情况下,必须使用小写的self 。 让我们看一个例子

依赖注入:Swift

你为什么要打扰? 使用DI,您的代码变为: 更容易测试 更容易扩展 易于重用 可可中常见的DI模式: 构造函数注入 在需要时,将依赖项作为对象创建本身的一部分传递给对象。 2.财产注入 通过设置对象状态值或属性传递所需的依赖项时。 3.方法注入 当需要的依赖项通过调用对象的方法来传递时,将根据需要更新对象的初始状态。 可可大量使用所有这三种DI模式。 如果您使用了Storyboards或xibs,则在创建IBOutlet时,它将使用属性注入将它们加载为初始值。 常用的DI反模式: 混蛋注射 控制怪胎 普通DI容器: 界面生成器 台风https://github.com/appsquickly/Typhoon Swift注入https://github.com/Swinject/Swinject

Swift中的委托模式

刚进入软件开发领域,我首先开始学习用Python编写代码,然后再学习Java。 两种语言都是进入面向对象编程世界的绝佳机会。 但是,直到我开始学习Swift时,我才遇到了委托模式。 许多人警告我,由于这是一个新主意,因此可能需要一些时间来学习和习惯。 我准备好自己,看了一些视频,并完成了一些教程,但是第一次遇到一个复杂的话题时,有时会遇到挫折和困惑。 我继续前进,并自信地将其从我要学习的新主题列表中删除。 我以为,如果我在项目中需要它,我已经获得了足够的知识,至少可以查找它并将其轻松集成到我的代码中。 当机会出现在实际项目中使用它时,我很快意识到我对自己的理解并没有我想象的那么好。 此外,我很难找到一种资源来列出所需的代码行以及它们如何在涉及的两个类之间组合在一起。 我再次“打书”(隐喻地,我完全使用了互联网。)并开始了一个过于简单的实践项目,该项目隔离了授权模式,以便在它起作用之前我可以一直使用它,并且我完全理解了概念和用法。 因此,我对所学内容进行了反思。 代表团 简单来说,委托允许两个类进行通信。 从非技术意义上讲,委派(动词)是“将任务或责任委托给另一个人”(《牛津词典》)。 在技​​术世界中,除了对象之外,它是完全相同的。 该项目 我做了一个练习项目,该项目跟踪按下按钮时增加的计数。 我在这篇文章的底部包括了完整的代码,以及指向项目所在的GitHub的链接。 在我解释每个步骤时,请随时跳过或继续进行。 在第一个视图控制器中,我有一个显示计数的标签和一个通过segue移至下一个视图控制器的按钮。 在第二个视图控制器中,我只有一个按钮来更新计数。 在第二个视图控制器中,我可以多次点击“更新计数”按钮。 它将当前计数打印到控制台。 完成后,我可以在顶部的导航控制器中进行回溯,并看到第一个视图控制器中的计数标签已更新。 以下是我在第二个视图控制器上单击“更新计数”五次并返回到第一个视图后的示例。 如果我在不关闭应用程序的情况下再次重复该过程,它将继续从我上次中断的地方开始更新计数,在这种情况下为5。 代码 设置委派模式需要使用几行代码。 这里将扮演三个更大的对象:定义需求的协议,符合协议的类(即委托)和访问属性或调用协议中概述的方法的委托类。 定义协议 对于此示例,需要在两个类之间传递的唯一操作是增加计数器。 协议本身就是对象。 关键字协议是必填项,后跟用户提供的名称以及方括号。 该名称的处理方式与类名或枚举相同,其中首字母大写。 通常,在委托模式中使用时,协议名称将包含单词“ Delegate”以阐明其用途。 在方括号内,我定义了所需的方法。 我使用关键字func来指定我需要一个方法,该方法之后是我为其分配的名称,并带有开括号和闭括号。 协议IncrementCountDelegate { func gainCount() } 如果我的函数要返回某些东西或有参数,我会这样表示: func myFunction(参数:ParameterType)-> ReturnType 在协议中,我可能还需要一个属性,但对于此示例,则不需要。 虽然我知道我的方法gainCount()最终可能会需要一个称为count的属性,但委托类不一定需要了解它,因此我没有在协议中包括它。 以后再说。 但是,如果确实需要包含一个属性,则该属性应如下所示: var myVariable:VariableType {获取设置} 设置关键字 […]

每周iOS Swift开发新闻#3

我将在本周最热门的图书馆,文章,工具和教程中谈论与我们钟爱的编程语言:Swift相关的事情。 RXVIP:干净的主动架构: 通过安德鲁·麦克卡鲁斯(Andrew Mackarous) 在Swift Dev News#1中,我给了您一个指向Clean Swift的链接,Clean Swift是Swift的干净架构,也称为VIP。 好吧,本文是关于将Clean Swift(VIP)与Reactive Swift(RxSwift)结合使用的。 我对RxSwift并没有那么丰富的经验,但是我对RxSwift所做的一切使我注意到它的功能强大,然后与Clean Swift架构混合在一起…… 移动应用内购买优化的终极指南: 由Hady Elhady 开发应用程序时,我们要发布的主要原因之一是对社会产生影响,并使生活更轻松,这是一个好的应用程序的含义,但是还有其他目标需要实现。 我们在谈论金钱。 在本文中,您将学习如何吸引用户并使他们想在您的应用上花钱。 什么样的功能可以销售,订阅,删除广告,限价促销,捆绑销售……如果您想知道用户希望在应用内购买中看到什么,那么本文适合您。 如果您做得不错,并且拥有一些kickass高级功能,并且玩得好,您的用户将像这样: 完美的Swift:使用Swift的服务器端: 这类似于Vapor,是供开发人员使用Swift编程语言构建应用程序和其他REST服务的Web服务器和工具包。 您可以使用Swift进行所有操作 Swift 4.1更改摘要: 通过HackingWithSwift Swift 4.1通过keyDecodingStrategy改进了Codable Swift 4.1的新功能 Swift API设计指南: 来自swift.org的Swift编码的良好做法。 自动布局天堂的五个步骤: 通过艾格尼丝·瓦萨尔海里 我个人不喜欢以编程方式使用约束,但是本文说明了如何通过五个简单步骤来掌握约束。 也许您不喜欢以编程方式使用约束,但是本文值得一试。 查看Agnes Vasarhely谈论的关于避开安全区域的部分。 PodsUpdater: 通过Kizito Nwose 当您想更新Pod或获取特定版本时,您必须编辑Podfile,使用此OSX应用程序,您将拥有一个更好的UI。 当然您可以使用终端来做到这一点,但是毕竟我们除了可以使用终端之外,还使用SourceTree。 ARKit增强现实简介: 由KárolyNyisztor 本教程说明什么是增强现实,以及如何使用Apple的ARKit检测飞机并在第一个ARKit应用程序中使用3D对象迈出第一步。 创建自定义Xcode项目模板: 通过useyourloaf.com 如果您想创建自己的模板,而要使用空白页,标签页或单页,则本教程将通过简单的方法进行说明。 卡彻: 通过MountainBuffalo 这是另一个缓存库,但是完全在Swift中。 […]

如何在Swift框架中导入Objective-C框架

在正常的快速项目中,我们将创建一个桥接标题,然后将我们的Objective-C框架导入该桥接标题中。 对于框架,您将需要创建一个自定义的swift模块。 假设您有一个名为MyFramework的Objective-C框架。 首先,将您的框架添加到项目中: 然后,您需要将聚合添加到项目和目标列表。 输入Objective-C框架的名称作为产品名称。 然后转到构建阶段> +>新建运行脚本阶段。 输入以下脚本: 确保将头文件的路径设置为Objective-C框架的头文件的路径。 您可以在这里找到:https://github.com/AnumQ/public_scripts/blob/master/module.sh 从方案列表中选择聚合的MobileFramework,以建立聚合的MobileFramework。 现在,我们必须将框架包含在我们的项目中。 为此,我们将MobileFramework模块添加到主项目(框架)的Target Dependencies中。 现在构建您的MyCustomFramework项目。 通过添加import语句,只需在swift文件中使用框架: 哇!

在Swift中使用NSNotificationCenter

NSNotificationCenter可以被视为在您的应用程序中传达信息的工具。 与推送通知或本地通知不同,在这些通知中,您会通知用户您希望他们接收的任何内容,NSNotificationCenter允许我们根据应用程序中发生的操作在类和/或结构之间发送和接收信息。 简而言之,可以将NSNotificationCenter视为广播公司,我们可以收听不同的电台或频道以收听任何更改。 NotificationCenter.default是所有通知发布和观察对象的位置。 每个通知都必须具有一种独特的方式来标识自己,如果继续进行类比,则该方式将代表我们要进入的频道。 同样,如果我们要观察或收听任何频道,则可以通过NotificationCenter.default调用对我们可用的观察方法,并基于此侦听执行某种类型的操作。 我创建了一个简单的应用程序,该应用程序演示了NSNotifcationCenter的用法,以便我们可以更好地理解代码中的形式以及它的实际工作方式。 如果您像我一样,并且是动手学习者,请随时进行编码。 在此应用程序中,我嵌入了导航控制器,并连接了所需的所有IBOutlet和IBAction。 该应用程序的目标是显示从其他视图控制器中选择的目的地的名称。 首先,我们将创建在NotificationCenter在给定通道中检测到更改时将执行的操作。 在我们的案例中,我们正在创建两个函数,这些函数将更改ChoiceDestinationVC中的城市标签。 func setToPeru(notification:NSNotification){ cityChosenLabel.text =“秘鲁” } func setToArgentina(notfication:NSNotification){ cityChosenLabel.text =“阿根廷” } 每个函数都会将cityChosenLabel设置cityChosenLabel相应的文本。 我们将不会对这些功能做任何事情,但是很快,当我们开始在应用程序中进行观察时,我们将对其进行调用。 还记得我提到每个通知应具有唯一身份吗? 好了,我在Notification.Name上创建了一个扩展,并在每个通道的名称上添加了两个静态属性。 通常,您可以手动键入包含您要在调用observe或post方法时用于通知的名称的字符串,但这可以帮助我们避免错误,并减少因拼写错误而导致错误的空间。 扩展Notification.Name { 静态让秘鲁= Notification.Name(“秘鲁”) 静态让阿根廷= Notification.Name(“阿根廷”) } 之后,我们将在ViewDidLoad中添加观察方法,这些方法将侦听其指定的通道并根据每个通道执行操作。 NotificationCenter.default.addObserver(自身,选择器:#selector(setToPeru(notification :)),名称:.peru,对象:无) NotificationCenter.default.addObserver(自身,选择器:#selector(setToArgentina(notfication :)),名称:.argentina,对象:nil) 我们的第一个观察者方法将执行我们上面创建的功能setToPeru(notification:) ,如果通知已发布到.peru通道,我们将在其中更改标签的文本。 然后将相同的内容应用于侦听并将标签文本更改为阿根廷的setToArgentina(notification:) 。 从这里开始,我们进入下一个视图控制器DestinationVC。 当有人单击任一按钮时,我们将在此处发布通知。 @IBAction func peruButton(_ sender:Any){ NotificationCenter.default.post(名称:.peru,对象:无) } @IBAction func argentinaButton(_ sender:Any){ […]

在Swift中重写应用程序,第2部分

大家好,欢迎来到本系列文章的第二部分,我将向您展示如何在Swift上重写Todo Rugby。 在第一部分中,我向您展示了如何使用Drawer,Tab和NavigationManager以编程方式构建骨架。 在这一节中,我将介绍以下几点: 联网:使用Moya编写服务层,以及全新的Codable协议,这是Swift 4的一个很酷的功能。 基类:为什么要考虑使用它们。 平等:如何以Swift方式实现旧的isEqual 。 guard let :您的所有可选问题的战刀。 莫亚 网络层是处理API数据的任何应用程序中非常重要的一部分。 阅读并研究了可用的最佳工具和Pod之后,我介绍了Moya,这是一个网络抽象层,其内部使用Alamofire(Swift AFNetworking的继承者)。 该框架的有趣之处之一是,您不必在每次启动新应用时都重写新的网络客户端。 它在内部处理。 您必须指定的唯一内容是: 枚举:您的所有请求都将在枚举中定义,包括其参数和其他数据。 基本网址:用于访问您的API的网址。 端点:对于每个新的枚举,您必须告诉他们哪个是该枚举的关联端点,以及它应如何处理该端点上的参数。 方法:应该为每个枚举值( .get , .post等)使用的HTTP动词。 任务:请求应为纯请求还是具有其他数据(查询字符串参数,表单数据,多部分等)。 标头:您应为每个端点使用哪些标头。 样本数据:是的,因此,如果您提供端点,则可以模拟端点。 在使用“抽屉”和“选项卡”设置导航之前,我一直喜欢做的事情是控制更新,以及是否应强制执行该更新。 也就是说,如果用户仍然可以使用与更新有关的应用程序,或者唯一的使用方式是通过更新来使用它。 我没有介绍如何编写您的强制更新逻辑,但是我要介绍的第一个端点是version 1。 在实现符合TargetType协议的Service枚举后,您应该具有以下内容: 有关JSONDecoder类如何处理结构及其键的更多信息,请从第24分钟开始观看此视频。 继承是OOP的强大工具,您应该始终尝试利用它。 在iOS(在本例中为Swift)上,我喜欢以下基类: BaseViewController 它继承自UIViewController并具有方便的方法来处理NavBar设置,屏幕跟踪以及更多其他功能。 BaseTableViewCell 可以想象,它继承自UITableViewCell并具有非常有用的方法。 它还具有一个model属性,该属性是实现Decodable协议的结构。 看起来像这样: 可能您从未实现过isEqual方法。 我认为其原因之一是因为它花费了大量代码: isEqualToTournament是一个方便的方法,例如isEqualToString或isEqualToNumber ,因为知道接收者来自同一类,所以您可能会使用此方法。 但是,如果要对列表进行排序或使用在isEqual使用isEqual集合进行操作,则必须实现它。 使用Swift,我们有一个了不起的功能,称为运算符重载(如果您使用C ++编写代码,您可能知道我在说什么)。 基本上,您可以覆盖运算符以对对象执行自定义操作。 在这种情况下,我们将覆盖==运算符,以便可以使用它检查两个对象是否相等: 惊人! 现在,每次您在两个锦标赛之间编写==比较时,它将使用此运算符并在内部检查其ID。 我要在这篇文章上谈论的最后一件事是关于尽早返回的一种编码样式,该样式检查并返回无效的情况,并使您专注于实际上将在您的方法上执行的代码。 […]

迅捷:回程与虚空

在返回语句之后,Swift将执行一个返回Void的函数,然后退出该函数。 在上面的示例中,由于打印函数返回Void,它将在退出myFunction之前执行。 此行为可能与其他控制语句(如guard)结合使用。 守卫的例子 但是, defer语句仍然在最后执行。 延迟示例 下面是一些其他带有(…)-> Void签名的愚蠢函数。 更多例子