Tag: swift

映射,过滤,减少,拖放Swift。 简单的高阶函数。

我已经对本文的主题进行了很多思考,并想向您介绍一些有用的且经常使用的简单高阶函数。 今天,我想整理一切,即使初学者也可以理解。 高阶函数对我来说很有趣,我将在这四个方面停下来:过滤,映射,缩小,删除。 当然,有4个以上,但是这些是最基本,最有趣的。 过滤器将此类元素返回给您的数组,并通过某个过滤器。 现在,我将向您展示过滤器如何在原始示例上工作: 传统方式 在emptyArray中,我们将具有以下数字:1、3、5、7、9。 代替这么长的代码,让我们使用filter : 结果,我们得到的答案是相同的,但是我们没有将空对象变成大量,也没有摆脱代码堆。 对数组中的每个元素执行操作以构建另一个数组。 想象一下,首先我们有很多成果: 现在让我们再创建一个由这些水果组成的数组。 传统方式 如果要使用map,我们将提供以下代码: 在此示例中,我们创建了一个名为fruitLowercase的空数组,该数组保留字符串值,并将simpleFruits的每个元素添加到fruitLowercase。 我向您展示了地图上最好和最短的版本,如果您想了解更多有关地图的信息,可以这样做,并将其留在下面的评论中。 过滤器帮助我们合并数组中的所有值并获得单个结果。 假设我们有一个任务要计算该数组中的所有字母。 这是一种传统方式: 传统方式 让我们看看,如果使用reduce将会怎样: 通过使用reduce将4行变成1。 0表示我们将开始增加多少。 当condition返回true时,从数组中抛出元素,返回false时停止。 之前: 传统方式 后: 它比以前容易得多。 好了,仅此而已! 我真的希望您能在项目中使用它,并使您的雇主惊奇。 今天,我向您展示了3种不同的高阶函数。 它们可以缩短您的代码并提高其可读性。 在评论中写下您希望我添加的内容,或在下一篇文章中写下。

UIPinch手势识别器

Herkese merhaba! UIGestureRecognizer serisinin ikinci ylan OIPinchGestureRecognizer ilekarşınızdayız。 Uygulamadakullanıcınındokunuşlarınıtespit edenyapıyaUIGestureRenignor deniyor。 点击,捏,平移旋转gibi dokunma hareketlerini bunlaraözelUIGestureRecognizer altsınıflarıilegerçekleştirebiliyoruz。 BuyazımızdaPinch konusunu elealcağız。 Vakit kaybetmedenbaşlayalım😉 UIGestureRecognizer Nedir吗? 手势识别器kulanıcınınparmak hareketleri ileetkileşimdeolan biryapıdır。 Farklıparmak hareketlerini特斯皮edip uygulamaiçibazıaksiyonlarıngerçekleşmesinisağlar。 UIGestureRecognizerKullanımAlanlarıNelerdir吗? Bir resminbüyütülmesinde,ekranda tersçevirilmesinde,üzerinetıkladığızamanbaşkabir resminaçılmasındave dahabirçokalandakarşımızaçıkmaktadır。 UIPinchGestureRecognizerKullanımAlanlarıNelerdir吗? Bir resmi veya herhangi bir nesneyibüyütülmesindeveyaküçültülmesindekullanılır。 UIGestureRecognizer AltSınıfları UITapGestureRecognizer: Kullanıcınınekrandayaptığıbasitdokunmalarıalgılar。 您可以在Instagramda bir照片上双击Double hareketi。 UIPinchGestureRecognizer: İkiparmaklayapılan,büyütmeveküçültmegibi hareketlerisağlayanyapıdır。 UIRotationGestureRecognizer: Döndürmehareketlerini […]

用继承编写可测试和可维护的代码

总览 软件工程师应努力实现的众多目标之一是构建可测试且可维护的代码,并且似乎许多人无法编写此类代码。 我敢肯定有很多原因会导致这一因素,例如完成项目的紧迫期限,或者工程师可能没有学习编写代码的正确方法。 我在Kaodim工作,我很高兴能有机会向我的前辈学习,并能够理解为什么我们倾向于以某种方式做事。 我记得在Kaodim编码我的第一个功能时,我在很多方面都感到不足,因此开始编写意大利面条式代码。 当我重新审视我的第一个功能时,我开始注意到我以前犯过的错误,并且我觉得自己可以做得更好。 供您参考,我的第一个功能称为“客户注册”,它允许新用户注册,而现有用户可以使用OTP功能登录。 这是该功能的技巧,但是随着我们深入研究,围绕它展开的逻辑很多。 对于这项功能,八月,我的上司创建了一个一次性密码库,我可以不时地对其进行修改,以适应该功能的需求。 代码气候测量 我们使用Code Climate来衡量我们的代码质量和可维护性。 在重构代码之前,我的PhoneNumberViewController和VerifyPhoneViewController的质量进行了如下测量: 继承方法 这里的计划是专门使用面向对象的编程继承,并且通过这种技术,我能够编写可伸缩且可测试的代码。 让我直观地向您介绍我们预期的代码结构。 为了让您更清楚地了解情况,我有两个父类,其子类数目灵活。 每个子类都将从父类继承,这样我就可以消除子类中的重复代码,并可以添加所需的任意多个子类。 让我以可视化的方式向您展示屏幕,然后给您一个场景。 作为新用户,我输入了我的电话号码,并被提示使用OTP代码进行注册。 然后,我通过短信收到我的OTP代码,并将其输入到我的验证屏幕上。 通过这种方法,我能够最大程度地减少代码中的冗余并拥有更简洁的代码结构。 但是,作为工程师,通过查看代码可以清楚得多。 我们将首先查看父类,在该类中,后端工程师创建了一个API,以检查电话号码以确定是否需要验证电话。 在满足不同条件的情况下,执行了不同的函数,但就我而言,我创建了几个空函数,这些空函数可以被子类覆盖。 比以前的分数高两个等级。 但是从可维护性来看,持续时间从24小时分别提高到25分钟和1小时有很大的提高。 我认为这是一个巨大的进步。 但是,我觉得我们仍然可以做得更好。 随之而来的是,所有子类创建的可维护性得分为A,0分钟。 快速而灵活地编写单元测试 我们将使用Quick&Nimble进行单元测试。 首先,我们将模拟自己的数据,而不依赖于API调用。 我们可以这样做,如下所示: 在这里,我们正在创建自己的模拟数据版本,以确定每个键的值,然后可以选择所需的返回值。 接下来,一旦有了模拟数据,就可以进行相应的测试。 首先,我们将测试电话是否被拿走,我们不允许用户注册。 我们可以通过选择checkNumberCase以返回我们需要的某些值来进行检查。 像往常一样,没有我的上校奥古斯特的帮助,我一个人不可能提出这种解决方案。 他在提出减少重复代码的解决方案方面做得非常出色,我得以在他的指导下实施该解决方案。 最后,我相信有很多不同的方法可以实现这一目标。 但是,我发现它可以以我的方式很好地工作,如果您以任何方式认为可以完成任何改进,请在下面随意评论。

Xcode矢量图像– Pdf

苹果,PDF矢量图像’i资产kataloğunaXcode 6sürümündeekledi。 PDF矢量图像,她的birdosyanın1x,2x ve 3xçözünürlükteki图像素材’lerinioluşturmaacısıolmayan pratik bir yoldur。 购买资产,例如androiddekullanılan。 Birgörüntüyütabanbüyüklüğününüzerinde菌种大小kötüvebulanıksonuçlarbırakabiliyordu。 PDFVektörAsset,xcode 9 iledeğişerek,vektörverilerini saklayabilme vegörüntüleriçalışmazamanındaölçekleyebilmeolanağısundu。 Aynızamanda dinamik tiplerle birlikteçalışabilenbazıerişilebilirlikiyileştirmeleride ekledi。 注释:她的pdf文档。 Örneğinbirfotoğrafaslavektörelolamaz。 Bunuiçinçizilmişbir resimolmasıgerekiyor。 Bunu en kolayşuşekildeanlayabilirsiniz。 pdf格式的文件objenin herhangi birkenarınıyapabildiğinizkadarzoomlayın。 Eğertransparan pikseller(sağdakigörselgibi)görürsenizbu dosyavektöreldeğildir。 PDF格式的矢量图像:资产类别资产负债表,格式pdf格式文件资产负债表。 图像资产kataloğuna1xçözünürlüklüpdfgörüntünüzüekleyip,özelliklerpenceresinden秤özelliği单秤olarakdeğiştirmenizyeterlidir。 Xcode构建zamanında2x ve 3xgörüntülerinidesağlamışolacaktır。 PDF ana ka PDF PDF imagelerininkullanılmasıylailgili问题,xcode’unölçeklenmişgörüntüleri建立了süresindeoluşturmasıydı。 Dahaönce运行时daölçeklenebilirgörüntülerkullanmakiçindestek yoktu。 Örneğin,普通koruduğundaiyigörünen100×100 pikselboyutlarındabiryıldız杀螨灵 在dolduracak kadar上查看,在genişletecek约束下查看eklersenizgörüntükötügörünür。 您可以在这里查看。 内容modunu Aspect Fityapıldı,Bir iPhone […]

调试内存不足问题:使用Runtime Magic捕捉布局反馈循环

让我们想象一下这种情况:您拥有一个成功的应用程序,该应用程序具有大量的每日用户和100%的无崩溃率。 您很高兴,您的生活令人赞叹。 但是在某个时候,您开始看到App Store出现负面评论,说它经常崩溃。 检查Fabric并没有帮助-没有出现新的崩溃。 那会是什么呢? 答案是OOM(内存不足)终止。 当您在最终用户的设备上使用RAM时,操作系统可以决定为其他进程回收该内存并终止您的应用程序。 我们将此称为“内存不足”终端。 可能有多种原因: 保持周期; 比赛条件; 废弃的线; 僵局; 布局反馈循环。 Apple提供了许多解决此类问题的解决方案: 解决滞留周期和其他类型泄漏的分配和泄漏工具 Xcode 8中已引入的Memory Debugger,它替代了Allocations和Leaks工具的某些功能 线程清理程序可帮助您查找竞争条件,废弃线程或死锁 布局反馈循环 我们将研究布局反馈循环。 这不是很常见的问题,但是一旦遇到,它可能会给您带来很多麻烦。 当您的视图运行其布局代码时,会发生布局反馈循环,但是某种方式导致它们再次开始其布局传递。 这可能是由于一个视图更改其超级视图之一的大小而导致的,或者可能是因为布局不明确。 无论哪种方式,此问题都会在您的CPU耗尽和RAM使用率稳定上升的情况下显现出来,这都是因为您的视图一次又一次地运行其布局代码而从未返回。 – 来自HackingWithSwift的Paul Hudson 对我们来说幸运的是,在WWDC16中,Apple花了整整15分钟的时间(!)引入了“布局反馈循环调试器”,该功能可帮助您识别调试期间发生循环的时刻。 这只是一个象征性的断点,它的工作方式就变得很简单:它计算在单个运行循环迭代中每个视图上的layoutSubviews()方法被调用的次数。 一旦超过某个阈值(例如100),该应用程序将在此断点处停止并打印一个不错的日志,以帮助您找到根本原因。 这是一篇不错的文章,简要描述了如何使用此调试器。 如果您可以重现此问题,则此方法非常适用。 但是,如果您有数十个屏幕,数百个视图,但您的App Store评论只说:“此应用程序很烂,总是崩溃,永远不要使用它!”? 您希望可以将所有这些人员带到您的办公室并为他们设置布局反馈循环调试器。 尽管第一部分由于GDPR而不能完全实现,但是您可以尝试在生产代码中复制UIViewLayoutFeedbackLoopDebuggingThreshold 。 让我们回想一下该断点是如何工作的:它计算一次layoutSubviews()调用,并在单个runloop迭代中超过某个阈值时发送一个事件。 听起来很容易,对吧? 该代码对于您的视图非常有效。 但是现在您想在另一个视图上实现它。 您当然可以创建UIView的子类,在其中实现它,然后从中继承项目中的所有视图。 然后对UITableView , UIScrollView , UIStackView等执行相同的操作…… 您希望可以将此逻辑注入所需的任何类中,而无需编写大量重复的代码。 这正是运行时编程允许您执行的操作。 我们将做同样的事情-创建一个子类,重写layoutSubviews()方法并计算其调用。 唯一的区别是所有这些将在运行时完成,而不是在项目中创建重复的类。 让我们开始简单-我们将创建我们的自定义子类,并将原始视图的类更改为该新子类: […]

可变的—通过Swift 4中的keyPath跟踪更改

我已经阅读了一些有关单向架构的文章。 有趣的是,您最想在状态更改时更新UI。 基本上,您将只观察状态更改,该更改将发送整个更改的状态,视图将在此状态下相应刷新。 问题在于,在UIKit中,我们没有虚拟DOM,它只能优化状态更改后需要刷新视图的部分中的视图刷新。 解决此问题的一种好方法是发送枚举,该枚举表示除了状态值本身之外状态上发生的更改。 但是我意识到,由于Swift 4中有keyPath,我们可以尝试使用它们来记录更改。 这就是我的意思,因此我编写了一个名为Changeable的小型框架,您可以在github上找到它。 Changeable框架是可容纳对象的任何类型的包装,并为您提供以下功能: 通过keyPath set属性更改 set方法不会立即应用更改 commit方法将应用由set添加的未决更改 reset方法将还原触发set’s所有未完成的更改 观察commit后set所做的更改 可以,但是如何运作,对吗? 我将只关注实现的某些部分。 您可以在github上深入研究细节。 首先,让我们关注Changeable泛型类。 最有趣的部分是set方法,该方法存储keyPath和闭包,这些闭包将在包装的值中应用更改,以后在commit方法中应用更改。 因为没有简单的方法来存储keyPath并将其连接到值,所以需要applier闭包,因为WritableKeyPath是一个通用类,不能轻易以任何顺序存储。 我可以使用AnyKeyPath但是再次必须将它们转换为WritableKeyPath因为只有这种keyPath可以用于更改属性。 幸运的是, AnyKeyPath以及WritableKeyPath都具有hashValue ,该值可以帮助我将特定的keyPath与应用程序的闭包关联起来。 值得一提的是, hashValue仅保证在程序的一次执行中有用。 但是因为我们不需要将其存储在存储中,所以很安全。 另外, Changeable类具有添加观察者的能力。 我将省略许多文章中描述的观察实现。 但是更有趣的部分是,要发出然后消费更改, Changeable使用Change结构来保存更改的值和更改的keyPath。 这是Change结构的整个实现: 没有太多要说的了。 我不向您解释代码,而是向您展示如何使用它: 结论 keyPath在Swift语言中打开了一个新的可能性世界,它为该语言带来了一点活力。 我希望您会发现Changeable是可以用来解决实际问题的工具。 让我知道你的想法。 这就是我为您准备的一切。 您会在操场上找到更多内容,并在github上进行测试。

使用PromiseKit和Alamofire在Swift中下载图像

问题 如果我们必须从远程位置下载一些内容,则网络代码可能会变得非常混乱。 首先,我们必须知道要从中下载内容的路径(URL) (在我们的示例中为图片) 。 其次,可能该位置或路径将写入一些REST API端点请求中,并且在处理了JSON数据响应之后,我们必须开始下载图像,最后必须更新UI。 所有这些都必须在后台线程上完成,因为我们不想阻塞主线程,当然我们希望我们的应用程序保持响应。 此类问题的最佳解决方案是使用异步编程,并且如果我们希望我们的代码看起来非常整洁,则PromiseKit是最佳选择。 如果您不熟悉异步编程,请查看我以前的有关如何使用PromiseKit for Swift的文章。 接下来,我们将使用CocoaPods依赖项管理器安装PromiseKit和Alamofire库以用于网络请求。 要与其他依赖项管理器一起安装库,请访问PromiseKit的官方文档https://github.com/mxcl/PromiseKit和Alamofire https://github.com/Alamofire/Alamofire。 使用CocoaPods安装PromiseKit和Alamofire 如果您尚未安装CocoaPods,那么现在该进行安装了。 转到终端应用程序并输入: $ sudo gem install cocoapods 有关使用CocoaPods依赖性管理器的详细信息,请访问官方网站https://cocoapods.org/。 创建一个新的Xcode项目(Single View Application),并在项目目录中使用命令pod init创建新的podfile。 打开podfile并添加PromiseKit和Alamofire依赖库: 目标’YourProjectTarget’做 使用动态框架 use_frameworks! pod’PromiseKit’ 豆荚“ Alamofire” 结束 保存podfile,此时您可以在终端中使用pod install命令安装库: $ pod安装 从现在开始,您必须打开新创建的工作区文件.xcworkspace而不是.xcodeproj。 就是这样,现在我们可以在项目中使用PromiseKit和Alamofire了。 现实世界的例子 在本教程中,我们将从远程位置下载照片集。 我们假设照片的URL将在某些REST API端点中编写,并且出于本示例的目的,我们将使用占位符API https://jsonplaceholder.typicode.com/photos,该URL具有用于5000张照片的URL。 下载照片可能需要一些时间,因此我们将显示带有activityIndicator组件的预加载动画,并在下载完成后将其隐藏。 我们不会保留照片,它们将存储在临时数组[UIImage] 。 为了显示照片,我使用的是UICollectionView但是您可以自由使用任何可视组件进行显示。 采取的步骤: 显示预加载动画 获取并序列化json响应 下载照片 […]

复合数据源对象和功能方法要素

一旦我(好的,实际上是队友)面临着一项任务, UICollectionView另一个类型的单元格的UICollectionView添加一个单元格。 此外,仅在特殊情况下才显示该额外的单元格,这种情况发生在外部并且不直接依赖于UICollectionView 。 实施的解决方案催生了需要的if – else语句(如果内存UICollectionViewDelegate话)在UICollectionViewDataSource和UICollectionViewDelegate方法中,并且这些语句在生产代码中“安全地”存在了UICollectionViewDataSource UICollectionViewDelegate 。 在任务中,无需考虑更优雅的解决方案,就可以浪费时间和精力。 但是,我一直牢记这个故事,并沉思着一个可以由任意数量的其他数据源组成的数据源实现。 一个显然必须被概括,适合任何数量的原始数据源(包括零和一),并且必须与特定类型无关。 事实证明,它不仅可行,而且也不太复杂(尽管使代码看起来更漂亮有点棘手)。 我想使用UITableView的示例来分享我的先驱。 如果需要,必须容易实现类似的UICollectionView代码。 原始文章是用俄语撰写的,并在此处发表。 “观念永远比客观化更重要” 这是 Alan Moore ( 守望者 , V代表仇杀 联盟,非凡绅士联盟 )的报价(perharps incurate),但是作为程序员,我们真的很在意特定的实现,对吧? 我方法的主要概念是存储UITableViewDateSource对象的数组,返回其节的总数,并可以确定哪个原始数据源负责处理调用。 UITableViewDataSource协议已经具有获取节数,行数等所有必要的方法,但是不幸的是,由于特定的UITableView实例作为方法参数,我发现将它们用于我的目的非常尴尬。 这就是为什么我最后声明自己的协议,该协议扩展了UITableViewDataSource的一些额外要求: 协议ComposableTableViewDataSource:UITableViewDataSource { var numberOfSections:Int {get} func numberOfRows(用于Int)-> Int } 对于组合数据源,它成为符合UITableViewDataSource的简单类,并且可以使用任意数量的ComposableTableViewDataSource对象进行初始化: 最后一课ComposedTableViewDataSource:NSObject { 私有let dataSources:[ComposableTableViewDataSource] init(dataSources:ComposableTableViewDataSource …){ self.dataSources =数据源 super.init() } 私人替代init(){ fatalError(“ ComposedTableViewDataSource:必须使用带有参数的初始化程序。”) } } […]

Swift:{get}和{get set}之间的区别是,选择哪一个?

自从Apple在2015年WWDC推出面向协议的程序设计以来,可以在互联网上轻松找到很多关于面向协议的程序设计的优点以及如何在日常应用程序开发中使用它的文章。 但是,这些文章中的大多数都忽略了在适应面向协议的编程之前我们需要了解的最基本的知识之一–在声明协议的属性要求时,何时应使用{ get set }和{ get } 。 考虑一下我们有一个符合该协议的协议和一个结构,如下面的代码片段所示。 现在,让我们尝试创建MyStruct的实例并将一些值设置为myVar1和myVar2 。 不出所料,将value设置为myVar1时不会出现任何错误。 但是,即使我们使myVar2仅可获取,我们也能够将值设置为myVar2。 然后出现一个问题:“ { get set }和{ get }什么区别?” 现在,让我们尝试将MyStruct实例MyStruct MyProtocol类型,并将value设置为myVar1和myVar2 。 如您所见,现在尝试将值设置为myVar2时出现错误。 这是什么意思? 这意味着{ get set }和{ get }实际上是在协议级别为我们提供了所需的封装。 当我们在面向协议的编程中使用多态时,这特别有用。 假设您有一个Flyable协议,其中Airplane和Helicopter类均符合该协议。 您还具有SpeedLimitUpdater类,将使用它来更新所有Flyable速度限制。 想象一下,有一天您决定添加一个Bird类,并使它也符合Flyable协议。 等一下……这里有些SpeedLimitUpdater ,这是否意味着我们现在可以使用SpeedLimitUpdater类来更新鸟速限制? 显然,这是不允许的,因为bird不是机器,并且您不能设置它的速度限制。 为了解决这个问题,让我们将Flyable协议的speedLimit只设置为speedLimit ,将Bird类的speedLimit为私有。 SpeedLimitUpdater类的逻辑也需要更新。 如果您有兴趣,可以在这里找到完整的示例代码。 (只需将其粘贴到Xcode游乐场) 从上面的示例中,我们可以看到,在没有充分理由的情况下使用{ get set }将使您的代码更容易出错。 对我们来说, { get }更安全,让符合类型决定属性应具有的访问级别。 这是经验法则 : 在声明协议的属性要求时,请始终使用{get},除非您非常确定要同时设置它和settable。 我希望本文可以帮助您消除在声明协议的属性要求时所遇到的困惑。 […]

守护让日志#3

Bu sefer tam vaktindeyayınlananbir rapor。 💪Lakin bundanböyleraporformatındadeğişikliğegideceğiz。 🤔Dahaönceden5替代品3替代品。 Bunun sebebidiğerikibaşlığıverimli olarak dolduramayacakolmaktı。 Yineöğrendiğimveyaptıklarımıbelkikısacabu paragraftapaylaşabilirim。 Lakin bir altbaşlıkiçerisineyerleştirmeyeceğim。 达哈sıkıaraştırmalaryaparak,达哈çokokuyarak ve izleyerek sizlerlepaylaşacağım。 Eveeet gelelim raporumuzda yer alacak verimli linklere…😎 İzlediklerim 奥库杜拉姆 关于Xcode 10新构建系统的五件事 Apple在预览模式下发布了带有Xcode 9的Xcode New Build System。 当时默认情况下未激活它。 Swift的100天-使用Swift进行黑客攻击 通过关注100天免费教程 www.hackingwithswift.com 了解Swift UyumadanÖnceNeden EkranlaraBakmamalıyız? Maviışığınzararları! medium.com iOS代码签名和设置 Xcode发行商代码签名与供应配置文件的代码签名。 匈牙利语seviyemizigeliştirmeküzerine 盖伦isteklerüzerineİngilizceseviyemigeliştirmedeneyimlerimipaylaşıyorum。 medium.com 搜索词Nedir? Uygulamamızınbaşlık,altbaşlık,küsave uzunaçıklamagibi alanlardakullanacağıanahtar […]