Tag: swift

如何在Swift中实现自己的Optional Chaining

深入了解.map和.flatMap运算符 自从我开始使用Swift进行编程以来,我不禁在对数组执行各种操作时使用map , reduce , filter等函数。 关于它们的事情是如此令人愉快,以至于我永远不会错过将我通常的数组处理例程变成这些漂亮的函数运算符链的机会。 但是,如果我告诉您可以将这一概念的使用范围扩展到集合类型之外呢? 对于您来说,这可能不是什么大新闻,但您可以将map运算符与Optional类型一起使用。 没有什么比老的“ Hello world”更好地说明编码问题了。 这是一个接受字符串并以“ Hello”为前缀的函数: map用于将可选值转换为另一个值(可能也是不同类型)。 如果可选值中有一个值,那么它将遍历整个转换链。 如果不是,它将继续返回nil 。 简单。 map用于将一个可选值转换为另一个可选值。 nil的行为不会改变,但是对于非nil值,其他所有转换都会增加一层嵌套,例如,您将从.some(T)转到.some(.some(U)) ,然后.some(.some(.some(V)))等。 就像前面的示例一样, flatMap用于将值转换为另一个可选值。 但是,每个新层都被“展平”到当前级别,因此最后只剩下一个Optional对象。 类似于保龄球从车道上掉下来并不断滚滚落下,一旦该值变为nil所有后续转换都将被忽略,并且一直保持nil直到链结束。 希望这可以使您更好地了解这些功能的行为方式以及它们为您带来的好处。 您可能还会注意到,此概念经常针对各种数据类型实现。 例如,一种非常流行的Result类型,广泛用作来自网络请求的值和错误的容器。 许多实现(例如这种实现)也支持map和flatMap功能。 但是,等等,还有更多。 再次查看图片,特别是flatMap部分。 这种行为会让您想起某些事情吗? 执行会沿着可选值的链进行下去,直到成功完成或达到nil为止。 如果您考虑一下,“可选链接”的工作方式完全相同。 因此,必须有一种方法可以仅使用map和flatMap运算符提出我们自己的Optional Chaining实现。 假设我们不使用转换函数,而是要访问某些属性。 从Swift版本4开始,我们可以通过传递属性名称作为函数参数来使用KeyPath语法来访问属性。 然后,我们将使用flatMap读取可选属性并map以访问非可选属性。 为了模仿原始语法,我们将编写一个扩展名并使用最喜欢的某个运算符,即~> 。 扩展名如下所示: 借助方法重写的强大功能,我们在处理普通变量和可选变量时都可以使用相同的方法签名,这将导致语法均匀,因此使用这些运算符的人将不必知道底层的方法。 试试看! 此新运算符可以用作内置链接语法的替代方法。 像这样: 几乎没有区别,您可以互换使用它们! 如您所见,“可选链接”并不是什么魔术,而仅仅是一种语法糖,它是一种机制的糖,您可以使用高阶函数的功能自行实现该机制。 现在,您知道了如何利用map和flatMap来编写更多声明性代码,并且已经准备好处理RxSwift之类的功能范例。 不要忘记Swift是开源的! 如果您想了解更多信息,可以自己研究Optional类型的源代码。 编码愉快!

玩今天的窗口小部件扩展第一部分

首先; “乐趣”在这里是主观的! 对我来说,什么是“乐趣”( 不 使用情节提要 本机进行iOS原生开发 …… ),对其 他人而言 可能是无聊的(或…… 折磨 ?)。 * Kanye耸了耸肩* ……实际上……现在或以后再也没有提及Kanye了。 免责声明 :本文假定您熟悉:使用 Swift 本机开发iOS应用程序 。 各种iOS框架,API和组件……或至少是; 安装了 XCode 。 与往常一样,您甚至没有义务阅读此书,您可能只想要源代码,就 在这里 。 因此,您可能想知道“ Today Widget到底是什么?” 简短答案:“今日视图”中的应用扩展程序,可让用户快速访问信息。 不确定那是什么意思? 好吧, 这是一个很长的答案 。 让我们通过创建一个新的XCode项目来开始。 接下来,添加应用程序扩展 时间到一些代码 现在,这是我完全删除所有情节提要的部分。 main和launchscreen(您不必完全删除它们,但是我不会使用它们),而是将AppDelegate配置为手动启动默认的ViewController 。 现在,您的项目应该在主应用程序和Widget扩展之间显示清楚的区别。 从现在开始,您基本上将专注于Widget扩展名称空间。 创建一个名为UserModel的快捷文件,此模型对象将具有一个名为’name’的字符串变量。 进口基金会 struct UserModel { 命名:字符串 } 创建一个新的Cocoa Touch Class,将其设置为UICollectionViewCell ,并将其命名为UserCell。 这将是自定义的collectionview单元格,其中将容纳将在小部件上看到的必要视图( […]

储存使用者资料

对于许多应用程序而言,一个真正重要的功能是能够存储用户数据。 您的应用在各个方面都可能令人赞叹,但如果它不记得用户做了什么,那就会很烦人。 您可能要存储数据的原因包括: 用户设置 游戏高分 档案信息 留言内容 还有许多其他。 幸运的是,这根本不是一件困难的任务。 使用NSUSerDefaults类可以非常容易地存储诸如Strings和Integers之类的简单项目。 NSUserDefaults类提供了与默认系统的接口,可以对默认系统进行自定义以匹配用户的首选项,例如度量单位。 要在其中设置自己的值,请使用以下代码行: NSUserDefaults.standardUserDefaults()。setValue(,forKey:) 举个例子: NSUserDefaults.standardUserDefaults()。setValue(“ red”,forKey:“ colour”) 在这里,我们将字符串“ red”存储在名为“ colour”的键下。 您可以存储任何标准类型,例如Float,Int,String。 要在下次运行应用程序时检索此密钥,我们只需要从给定密钥中索取值,例如: 让SavedColour = NSUserDefaults.standardUserDefaults()。valueForKey(“ colour”)设置为? 串 现在,请注意,您要查找的数据实际上并未显示在手机上。 也许用户已经删除了数据,或者这是该应用程序第一次运行。 不会创建任何密钥。 因此,当您使用此值时,应用程序可能会崩溃。 始终最好在此类声明周围加上保护性声明,例如: 如果让saveColour = NSUserDefaults.standardUserDefaults()。valueForKey(“ colour”)设置为? 字符串{ //在这里使用您提取的数据 } 其他{ //在此处设置默认值供您的应用使用 } 这一切都很棒,并且非常容易实现。 但这不适用于任何自定义类。 存储自定义类 假设您已经创建了一个Person类,该类存储了他们的名字和姓氏: 类人 { var firstName:字符串! var lastName:字符串! 初始化(第一个:字符串,最后一个:字符串) { firstName […]

服务器端Swift — MVC(单元测试)

在我的上一篇文章中,我描述了如何根据MVC模式(与ASP.NET MVC类似的构建)构建服务器端Swift应用程序。 但是,这里缺少一件事: 单元测试 。 没有单元测试,我无法想象认真的应用程序。 在本文中,我将介绍如何在Swift(和Per​​fect框架)中向我们的MVC应用程序添加带有单元测试的项目。 首先,我们必须重新构建一些应用程序。 我们无法为可执行应用程序创建单元测试。 这就是为什么我们必须将应用程序分为两部分: 可执行文件 -这部分应包含尽可能少的文件, 库 -该部分应包含整个业务逻辑-这部分我们可以连接到我们的测试库。 划分应用程序后,我们应该有一个如下所示的项目: 来源/ TaskerServerApp / 主Swift TaskerServerLib / 控制器/ * 楷模/* 仓库/ * 扩展名/ * 测验 TaskerServerLibTests / 因此,我们有TaskerServerApp可执行文件,其中仅包含一个文件(引导我们的服务器的主文件)。 我们有TaskerServerLib ,其中包含业务逻辑的主要部分(控制器,模型,存储库等)。 在单独的项目TaskerServerLibTests我们将进行单元测试。 要创建该项目,我们必须为Swift Package Manager准备Package.swift文件。 它看起来应该像这样: 现在我们必须考虑如何创建伪造的实现。 在像C#/ Java这样的语言中,我们可以使用功能强大的模拟框架,例如:Moq,Rhino.Mocks,mockito。 不幸的是,在Swift中,这项任务并不是那么容易。 Swift的反射/自省能力不足,无法在运行时生成动态类(在许多被称为代理的模拟框架中)。 我发现了一些模拟库,例如: SwiftyMocky-我们可以标记协议( //sourcery:AutoMockable ),然后适当的伪造实现将由Sourcery工具生成, Cuckoo —特殊的生成器( CuckooGenerator )和框架,generator负责基于配置文件生成伪造的实现, Mimus —框架,提供我们可以在人工生成的假文件中使用的方法(目前仅支持模拟), Dobby-与Mimus相似,但是在我们的虚假实现中,我们可以使用模拟和存根。 […]

Swift 4 Introduction系列1.6 — Swift数据类型可选

Optionals是一个后缀运算符,可以附加到任何数据类型。 可选项目以问号( ? )表示。 我们使用可选参数来指示变量所分配给的数据类型可以不包含任何值。 我们使用关键字( nil )分配一个没有值的可选内容。 只有声明为可选变量的变量才能分配nil值。 我们在某些情况下声明了可选变量,在这种情况下我们不知道输入源是否包含数据。 可选选项使程序更安全地进行编码。 例如,声明为( Int? )的变量; 告诉系统该变量可能没有任何值。 我们可以测试变量是否有值,如果有值,可以从变量中解包值。 用于指示或声明可选选项的语法如下: ? 例如,要声明一个可选变量,我们执行以下操作: var someOptional1:Int? var someOptional2:String? var someOptional3:Double? var someOptional4:Bool?someOptional1 someOptional2 someOptional3 someOptional4 请注意,在声明可选变量时,我们不需要初始化变量,因为可选变量数据类型变量会自动初始化为无值或nil。 但是, 自动初始化仅适用于变量,不适用于常量。 我们可以使用值设置可选选项,如果程序需要设置为nil,则将它们重置为nil。 例: //从先前的代码继续 someOptional1 = 766 someOptional3 = 7123.98 someOptional4 = falsesomeOptional1 =无 someOptional4 = nilsomeOptional1 someOptional2 someOptional3 someOptional4 请注意,在Objective C中找不到可选参数。尽管我们可以在Objective-C中将对象设置为nil,但在Objective-C中,nil指向空指针,而在Swift中,我们可以将任何数据类型设置为可选参数。 我们还可以同时声明和分配可选内容。 […]

Swift 4中的多个ViewController(第1部分)

系列 Swift 4中的多个ViewController(第1部分) 如何在Swift 4 medium.com中使用Multiple ViewController Swift 4中的多个ViewController(第2部分) 如何在Swift 4 medium.com中使用Multiple ViewController 彭根纳兰 Dalam bahasa程序swift kita bisa membuat lebih dari satu view dengan satu view controller yang sama。 Akan tetapi akan lebih bagus jika massing-masing视图memiliki satu视图控制器。 Dengan demikian kita bisa lebih mudah dalam mengatur fungsi atau setiap property pada masing-masing view。 Khusus untuk入门教程ini Mungkin,Akan,Berguna,Agar,Lebih,Memudahkan,Dalam,Membuat,Aplikasi,Yang […]

使用UIFeedbackGenerator的触觉反馈和Taptic Engine改善iOS应用程序用户体验

在我的上一篇文章中,我写了关于在任何UIView中引入3D Touch作为通用UIGestureRecognizer来改善与您的应用程序的交互的信息,现在我想探索触觉反馈,这为我们提供了一种新的物理方式来控制用户所发生的事情在他的iPhone上。 在通过Taptic引擎提供触觉反馈之前,播放声音是向用户提供有关应用程序中动作的反馈的唯一方法,但是声音令人讨厌,有时令人毛骨悚然。 UIKit为此提供了一种简洁明了的方法:用于触觉反馈即插即用实现的标准安全接口UIFeedbackGenerator。 在特定的UIFeedbackGenerator中,是一个我们不能直接使用的抽象超类,我们必须在3个具体的子类中进行选择,每个子类都有特定的使用目的地。 UISelectionFeedbackGenerator 当用户通过一系列离散值更改选择时,例如在Apple通过诸如UIDatePicker之类的选择器移动Apple时,提供此反馈。 在实现自定义分段控件或更改任何选择时,可以在多个选择表视图和集合视图上使用它。 UIImpactFeedbackGenerator 该反馈旨在用于模拟Taptic引擎的物理影响。 UI元素固定到位或某些元素碰撞时,请使用它。 它具有3个强度级别,您必须将其作为初始参数传递:轻,中和重。 Apple建议根据UI元素大小选择强度。 我还在自定义3D触摸手势识别器(在GitHub和我的Medium帖子中)中使用它,以中等风格提供有关成功手势的反馈。 UINotificationFeedbackGenerator 这是最完整的反馈生成器。 您应该使用它来传达任务或动作的结果。 与ImpactFeedback相似,它接受一个参数,但是这次不是init方法,而是运行Feeedback时。 这次的样式与强度无关,而是指通知操作的结果:成功,警告或错误。 选择一个表示用户已结束操作的结果。 UIFeedbackGenerator非常容易集成到您的应用程序中。 自iOS 10起可用,除非您支持以前的iOS版本,否则不必检查可用性,否则: 如果 #available ( iOS 10,*){ // UIFeedbackGenerator代码块 } 或更快捷的方式: Guard #available ( iOS 10,*) else { 返回 } // UIFeedbackGenerator代码块 现在,您可以初始化从3个可用类中选择的具体类,并确保选择一个适合用户操作的类。 让feedbackGenerator = UISelectionFeedbackGenerator.init() //要么 让feedbackGenerator = UIImpactFeedbackGenerator(style:.medium) //要么 让feedbackGenerator = UINotificationFeedbackGenerator() […]

Swift并行编程:可能出什么问题?

在最后几篇文章中,我们研究了控制并发的不同方法。 操作系统提供了一些底层的基础知识。 例如,Apple提供了框架或其他想法(例如Promise),它们在JavaScript中得到了广泛使用。 即使前面已经提到了一些陷阱,但我意识到我没有给予他们足够的荣誉。 因此,为全面起见,本文进行了部分概述。 本文的目的是,如果您不了解并发性,可能会出错。 让我们潜入吧! 原子包含与数据库上下文中的事务具有相同的想法。 您希望一次将所有值写入一个操作。 当使用int64_t而不具有原子功能时,编译为32位的应用程序可能会出现奇怪的行为。 为什么? 让我们详细了解会发生什么: int64_t x = 0 线程1: x = 0xFFFF 线程2: x = 0xEEDD 进行非原子操作可能会导致第一个线程开始写入x。 但是,由于我们正在使用32位操作系统,因此必须将写入x的值分成两批0xFF。 当Thread2决定同​​时写入x时,可能会按照以下顺序安排操作: 线程1:part1 线程2:part1 线程2:part2 线程1:part2 最后,我们将获得: x == 0xEEFF 既不是0xFFFF也不是0xEEDD。 使用原子,我们创建一个单一的事务,这将导致以下行为: 线程1:part1 线程1:part2 线程2:part1 线程2:part2 结果,x包含Thread2设置的值。 Swift本身没有实现原子。 关于Swift进化,有一个建议添加它,但是目前,您必须自己实现它。 就在最近,我不得不修复一个崩溃,该崩溃是由于从两个不同的线程写入一个Array而导致的。 还记得Swift并发中的错误处理吗? 它包含一个错误,很容易忽略。 如果组中的两个操作可以并行运行并且同时失败,会发生什么情况? 他们将尝试同时写入错误数组,这将导致Swift.Array中的“分配容量”崩溃。 要修复它,该数组需要是线程安全的。 一种选择是:同步阵列。 但是通常,您将必须锁定每个写访问权限。 不要误会我的意思,阅读也可能会失败: 一个简单的例子是拥有一个银行帐户,需要执行交易。 此交易分为两个部分:第一笔提款和第二笔存款。 […]

iOS版Menampilkan Waktu Secara实时

[Artikel di edit lagi kapan-kapan] 帕凯Timer var timer = Timer() buat属性ti dateFormatter自然属性视图DidLoad dateFormatter = DateFormatter() dateFormatter?.dateStyle = .medium dateFormatter?.timeStyle = .medium dateFormatter?.dateFormat =“ hh-mm-ss a” PERHATIKAN dateFormat“ hh — mm — ss a” viewDidLoad() 覆盖viewDidLoad(){ timer = Timer.scheduledTimer(timeInterval:1,target:self,选择器:#selector(printDateRealTime),userInfo:nil,重复:true) } printDateRealTime() 让一个= dateFormatter?.string(from:Date()) 打印(一个!) 塔拉!

Swift 4中的iOS UIKit:创建带有动画的按钮

预习 资源 项目 https://github.com/calmone/iOS-UIKit-component 参考 UIButton https://developer.apple.com/reference/uikit/uibutton CGAffinTransform https://developer.apple.com/reference/coregraphics/cgaffinetransform 快乐编码😄