Tag: swift

编码与对象映射器

我最近一直在尝试使用Swift的新Codable协议,以将从远程服务获取的JSON映射到Swift模型对象。 出于某种背景,在Swift 4中添加了Codable,作为一种干净地允许对象将自身转换为外部表示的方法。 可编码本身只是可解码和可编码的一种类型。 在这篇文章中,我将重点介绍Decodable部分,因为它是我感兴趣的远程JSON表示形式的转换。 比较方式 过去我曾经广泛使用过ObjectMapper,但由于Codable现在已内置到Swift中,所以我想对两者进行比较。 我要比较的功能是: 验证🕵️ 自定义转换(映射到自定义类型,例如将JSON字符串映射到正则表达式) 错误处理⚠️ 我要解析的数据是我们为BBC Sport应用远程获取的真实配置 这是一个相当简单的JSON结构,但是它有几个正则表达式,我想将其映射到NSRegularExpression ,而不是String 对象映射器 使用ObjectMapper映射此JSON模型所需的结构如下。 这些结构都符合ImmutableMappable 协议,这意味着他们需要一个构造函数,该构造函数接受Map对象,如果映射失败,则抛出错误。 验证方式 要执行验证,您可以使用Optionals。 在此示例中,我们确定该应用程序可以在没有这些电子邮件地址的情况下运行,因此这些电子邮件是可选的。 如果不存在键或无法将其map.values(“emails”)转换为正确的类型,则map.values(“emails”)会引发错误。 我们利用try? 捕获该错误,如果有错误,只需将其转换为nil值即可。 如果我们确定特定属性是必需的,那么我们就不会将其标记为可选属性,并允许错误传播。 总体而言,使用ImmutableMappable验证非常简单 您可能已经注意到,在此调用map.value(“regex”, using: RegexTransformer())了另外一个参数map.value(“regex”, using: RegexTransformer())这是用于将String转换为NSRegularExpression的自定义转换,这使我的NSRegularExpression ! 自定义转换 ObjectMapper开箱即用地支持自定义转换,这非常简单。 在这里,我们只是实现TransformType协议和关联的transformFromJSON方法。 那需要一个类型,然后我们将其强制转换为String ,然后安全地try? 将String转换为NSRegularExpression 。 然后可以在任何地方重用此变压器reuse 错误处理 为了测试错误处理,我将使用缺少output键的JSON文件。 通过ObjectMapper运行此命令时,我们会收到一条非常有用的错误消息。 映射时出错。 -原因:无法转换为“字符串” -位置:Config.init(map :):30 -键:输出 -currentValue:无 它告诉我们快速找到问题所在的一切。 我发现使用AlamofireObjectMapper集成时,错误被抑制了,这不理想。 可编码 开箱即用的等效Codable实现如下 尽管使用CodingKey协议将键定义为enums但它与ObjectMapper非常相似。 […]

iOS:使用TouchID进行身份验证

嗨,大家好! 今天,我们将学习如何在Swift 3中使用Touch ID身份验证。 开始狂欢吧。 步骤1:创建一个新项目,并将其命名为TouchIdDemo 。 步骤2:在ViewController上,创建一种在视图显示后调用触摸ID验证的方法: 步骤3:不错! 现在,要使用触摸ID框架,我们必须导入LocalAuthentication框架。 点击您的项目: 滚动到底部,转到“链接的框架和库”并导入框架: 步骤4:转到ViewController并导入lib: 步骤5:在我们创建的authenticateWithTouchId中,创建一个上下文并检查触摸ID是否可用: errorPointer是一个变量,其中包含触摸ID不可用时的错误描述。 步骤6:创建一个名为requestTouchIdValidation的方法,并在authenticateWithTouchId上调用int: 步骤7:处理成功认证: 步骤8:处理错误验证 重要提示:触摸ID仅在物理设备上有效。 不要在模拟器上尝试。 Github项目:https://github.com/benhurott/ios-touch-id-demo

迅捷/金属图像处理

1.边缘检测 边缘检测是空间滤波的一种。 边缘是对象的外部限制。 在边缘,图像的亮度急剧变化。 边缘检测是为了计算图像中位置亮度的急剧变化。 如何计算仓位? 使用差分。 在连续域中,图像的导数为 其中f(x,y)是输入图像,与上一节中的I(i,j)相同。 当前计算将在离散域中执行,因此需要近似值。 (x,y)表示每个像素的索引,以金属表示。 因此,这些值的增量足够小。 可以使用以下近似值。 这只是一个减法!! 简单。 再考虑以下情况。 目标像素是I(2,2) 。 然后,目标像素两侧的增量为 水平: I(2,3)– I(2,1) 垂直: I(3,2)– I(1,2) 水平和垂直内核变成 试试这个过滤器。 SwiftImageProcessor/Shader/Edge/derivatives.metal准备SwiftImageProcessor/Shader/Edge/derivatives.metal 。 双for循环是卷积。 后一部分是颜色转换。 这将生成landscape_derivatives.jpg 。 可能会得到边缘。 根据内核定义了一些特殊的过滤器,并在我的项目中准备了这些过滤器。 威特过滤器 索贝尔滤波器 拉普拉斯 拉普拉斯滤波器在使用二阶导数方面与Prewitt和Sobel不同。 导数在图像处理中由增量近似,因此二阶导数为 在数学中,拉普拉斯定义为以下等式 这个方程很重要,但与下面的内核矩阵无关。 SwiftImageProcessor/Shader/Edge/laplace.metal 。 所以尝试一下。 其他文章 0.基本 2.平滑滤波器,高斯和双边

粒子发射器带来的乐趣

我喜欢HackingWithSwift网站和YouTube视频。 我认为保罗·哈德森(Paul Hudson)在用易于理解的术语和清晰示例来解释概念方面做得非常出色。 我一直想了解有关iOS动画的更多信息,以及寻找向iOS应用添加一些简单功能的方法。 斯威夫特问世期间 系列文章中有一篇关于Core Animation的文章,涉及绘制漂亮的白雪皑皑的背景。 在那篇文章中,我发现最有趣的是使用粒子发射器使雪花飘落。 我曾经在游戏中看到过粒子发射器,例如用于产生爆炸或魔术效果的游戏,但在非SpriteKit iOS应用中却没有。 这让我想知道可以使用粒子发射器创建什么其他效果。 粒子发射器是一种在应用程序屏幕上增加一点天赋的好方法,而无需在创建动画上进行大量投资。 在开始使用粒子发射器时,我首先创建了与Swift来临类似的降雪效果。 通过将CAEmitterLayer和CAEmitterCell与简单的渐变结合CAEmitterLayer ,可以创建一个非常简单的效果。 粒子发射器的代码相当简单,并从Swift的Advent中得到了充分利用。 要注意的主要元素是CAEmitterLayer和CAEmitterCell 。 让我们快速依次查看每个元素。 Apple文档将CAEmitterLayer描述为: 发射,设置动画和渲染粒子系统的层。 本质上,该层负责生成由CAEmitterCell定义的粒子(即雪)。 发射极层的重要属性是shape , position , size和mode 。 默认形状是point ,这意味着所有粒子都将从特定点发射。 还有其他几种形状选项,例如line , circle , rectangle甚至cuboid 。 发射器形状的大小和位置属性将影响其输出以及模式设置。 Apple文档将发射器模式描述为: 一个字符串,定义如何相对于发射形状创建粒子。 当前选项是“点”,“轮廓”,“表面”和“体积”(默认)。 在我们的粒子视图中, CAEmitterLayer被用作基础层。 但是,生成粒子的实际工作是由CAEmitterCell类完成的。 适用于CAEmitterCell状态的Apple文档: CAEmitterCell类表示由CAEmitterLayer对象发射的粒子的一种来源。 发射器单元定义了发射粒子的方向和属性。 发射器单元可以具有一个子单元阵列,该单元可以使粒子本身发射粒子。 可以将多种运动和时间属性应用于单元格。 我们将在后面的部分中进一步介绍这些内容。 降雪发射器中使用的主要参数是birthRate , lifetime , birthRate和birthRate 。 […]

使用Swift进行黑客攻击-挑战7

我知道,我至少要迟到一天,但是在贝尔格莱德,除了去看牙医,还有很多事情要做! -真的很难找到时间! 无论如何… 今天是第七个项目的挑战日 ! 不过,首先让我们回顾一下我们学到的所有很棒的东西: 使用Swift的Data类型进行JSON解码 使用Codable协议将数据转换为我们定义的Swift对象。 UITabBarController , UIStoryboard … 评论 从字符串创建URL可能会失败。 String , Int , [String]等都符合Codable 。 Swift的Data类型可以保存任何类型的二进制数据。 Codable协议可以将Swift类型与JSON相互转换。 情节提要标识符可以让我们用代码创建情节提要视图控制器。 UITabBarController能够存储多个视图控制器供用户选择。 UIStoryboard可以从我们的包中加载情节UIStoryboard并从那里创建视图控制器。 Apple提供了一些内置的UITabBarItem类型,以供一般使用。 JSONDecoder类型完成了将JSON转换为Swift值的艰苦工作。 我们可以直接从URL创建一个Data实例。 JSON是一种存储和发送数据的轻量级方法。 带有字幕的表格视图单元格显示两个不同的文本标签。 评论 当然,我只是在这里插入了正确的答案,但是,如果您有时间,请转到“利用Swift黑客”倡议的评论页面,然后看看其他答案。 许多人很坦率,但其他许多人却不……这就是保罗成为一位出色的老师的原因! 它给了您一些提示,但您必须从地下挖出金块! 挑战性 挑战1:使用UIBarButtonItem右上角添加一个Credits按钮。 轻按此按钮后,显示警报,告知用户数​​据来自Whitehouse的We The People API 首先,让我们创建一个按钮。 在这里,我不得不再次感谢保罗,因为我不费吹灰之力就知道该去哪里,怎么写以及怎么做! 这是我放入viewDidLoad()的代码: navigationItem.rightBarButtonItem = UIBarButtonItem(title: “Credits”, style: .plain, target: self, action: #selector(showCredits)) 这将创建一个具有.plain样式的按钮(即,仅带有文本的按钮),以self (视图控制器)为目标,而作为操作,我们仍然需要编写一种方法。 […]

使用ScrollView和AutoLayout

在使用UILabel,UIImageView等构建简单的UI时,使用AutoLayout非常有趣,但是当需要实现ScrollView时,我可以向您保证不是! 当您想实现ScrollView时,您必须知道的第一件事是,即使对于Apple工程师来说,这也非常困难。 因此,首先我们必须在视图控制器中放置一个ScrollView。 现在,我们开始配置ScrollView和子级的约束。 设置ScrollView约束 首先,我们必须将ScrollView调整为父级。 因此,我们单击“添加新约束”按钮,然后将其填充为: 现在我们将新的View放入ScrollView内,这将成为我们内容的容器。 设置内容视图约束 现在,第二步是在ScrollView中设置Content视图的约束。 首先,我们必须定义内容视图的宽度,然后父级(ScrollView)将调整为该宽度。 为此,我们必须在带有父视图的容器视图中设置“等宽”约束。 我们按Control +拖动以查看,然后单击“等宽” 现在,我们向内容视图添加新的约束以将其调整为ScrollView。 我们必须这样查看。 向内容视图添加内容 现在,我们只需将UILabel放到Content View内。 标签中的约束为: 和魔术发生! 我们已经安装了ScrollView,没有任何问题。 重要 如果您忘记在“内容视图”中添加内容,则必须将视图水平和垂直居中放置,否则Xcode将通知您警报。

具有可腐烂性的漂亮自构物体

这是一个分为四部分的系列文章的第三篇,该文章名为: Nifty,Swifty,API支持的App 。 您可以在 此处 分叉最终项目 。 第1部分:具有GitHub Pages的Nifty静态内容托管 第2部分:带有枚举的Nifty Bug-Safe URL 第4部分:带有NSCache的漂亮的自动缓存ImageView 介绍 在上一篇文章中,我们使用错误安全的网址获取了json数据。 现在,我们想使用该数据为我们的项目创建Person对象。 我曾经使用JSONSerialization来执行此类任务,它将根据输入的json数据生成一个字典。 构造所需的对象将需要遍历字典中的每个键,将值向下转换为所需的类型,然后将其分配给对象中的适当属性。 这很费力,并且容易出错,因为您必须键入每个键。 幸运的是,这现在是从json实现对象创建任务的“老方法”,并且现在有了Decodable协议,它非常安全且易于实现。 用可解码初始化对象 让我们从以下位置的json开始:https://timmybea.github.io/StaticHostingDemo/objectData.json 您会注意到,我们有一个键“ person”,其中包含一个数组json对象,这些数组包含我们的人员数据。 因此,让我们由内而外地进行工作,并从构造我们的Person对象开始: 我们的对象仅对json中的每个人信息都有一个属性。 现在我们可以遵循Decodable ,为我们的解码器创建密钥并设置我们的init方法。 在此代码中,我们遵循Decodable (第1行)的要求 ,并为我们的编码键(第9-15 行)创建一个枚举。 请注意,枚举类型必须为String并符合CodingKey协议。 对于每种情况,我们都分配与json键匹配的原始值。 接下来,我们实现协议初始化程序init(来自解码器:) (第17–27行)。 这涉及到使用.container(keyedBy 🙂 (第18行)将保存我们数据的解码器转换为KeyedDecodingContainer ,然后使用.decode(type :, forKey :)将每个键处的数据解码为所需的数据类型。 这些方法中的每一个都是失败的,因此初始化器被标记为throws,并在后台处理。 最后,我们调用成员明智的初始化程序,以使用成功向下转换的类型(第26行)构造我们的实例。 重要的是要确认,如果您的属性名称与json键的属性名称匹配,则只需要创建一个匹配的CodingKey即可快速神奇地构造您的实例,而无需定义初始化程序。 由于json通常不会采用这种方便的格式,因此此演示演示了完整的构建过程。 解析JSON 我们已经处理了Person实例的创建,但是请记住,所有person数据都可以通过json键“ person”访问 。 那么我们如何解析json来检索对象呢? 答案很简单:与上一节完全相同。 请注意,这一次我们只有一个[Person]类型的属性。 我们遵循与上一个示例完全相同的步骤,遵循Decodable […]

Swift 4集合类型

这个故事从根本上讲述了集合类型的声明和使用方法。 农历新年快乐2018 !!! 喔喔喔喔喔喔喔喔喔 有四种类型,包括: 数组 字典 组 元组 NSArray,NSDictionary,NSSet的Objective-C中的几乎所有方法都已迁移到Swift 4版本。 当然,由于SAFETY的Swift 4语言特性,对于那些刚从Objective-C那里碰到的人,会因快速声明的方式而有些恼火。 但是,它也可以让您实现更好的编码方式。 数组 var array1 = [1, 2, 3] var array2: [Int] = [1, 2, 3] var array3: Array = [1, 2, 3] 它们都是合法的书写方式,但是我将第二种格式清晰明了地指定。 字典 var dict1 = [“Dog”: 3, “Cat”: 5, “Rabbit”: 2] var dict2: [String:Int] = [“Dog”: 3, “Cat”: 5, “Rabbit”: […]

iOS生物识别本地身份验证

+ Shubaham Jain 实施TouchID身份验证 TouchID / FaceID是基于称为本地身份验证的框架的功能,该功能提供了用于从具有指定安全策略的用户请求身份验证的功能。 在应用程序中使用时,本地身份验证可以处理TouchID / FaceID的所有内容。 它将通过自定义消息提示您进行身份验证,该消息将告诉用户我们为什么需要身份验证,因此用户可以将手指放在主页按钮上。 本地认证框架 LocalAuthentication框架用于在iOS移动应用程序中实现TouchID或FaceID身份验证。touchId身份验证的使用基于本地身份验证框架。 为了实现touchId功能,我们首先在项目中添加了LocalAuthentication框架。 在项目导航中 ->选择目标->进入构建阶段->单击链接二进制文件与库->添加框架 在项目目标中添加LocalAuthentication Framework 现在我们可以编写代码了。 在AppDelegate类中,导入LocalAuthentication.framework 使用以下语句 @import LocalAuthentication; 下一步是要求框架通过评估策略功能可以将touchID应用于特定设备,它将接受两个参数,一个是我们要评估的策略名称,第二个是错误代码。 在App中实现TouchID时,请确定以下几种情况: Case 1 : Device is enabled with Biometric Sensor or not. Case 2 : At Least one Fingerprint is enrolled in device or not to check Biometric sensor availability. LAPolicy有两种类型, […]

Swift 4.2 Reduce和CoreLocation:总行驶距离🚗

在最近的一个项目中,我遇到了一个非常确定的问题,我敢肯定其他许多开发人员也会遇到:计算列表中存储的位置之间的总距离。 例如,假设您在由CLLocation对象列表表示的地图上有一条自定义路线。 您如何仅从CLLocation对象计算路线的总长度? 其背后的数学很简单,绝对没有理由写一个故事: 总距离等于列表中所有连接的位置对之间的距离之和 。 对于位置[A,B,C,D]的列表,可以表示为: | AD | = | AB | + | BC | + | CD |。 但是,可以使用我们位置对象上提供的函数distance(from :)以不同的方式完成该实现。 样板解决方案: 使用传统的面向对象方法,可以通过几个变量和位置迭代来解决此问题: 样板解决方案 该实现完全按照我们的预期工作,并且对于任何初看它的开发人员来说都是可读性和可理解性。 但是(没有双行中断),对于需要参考下一个/上一个元素以及将在集合迭代期间进行调整的变量的任何给定问题,最有可能重写这9行代码因此命名为样板解决方案)。 递归解决方案: 递归专家将很快意识到这是一个递归问题:我们为递归列表的一部分积累一个临时结果,并使用积累的结果对列表的其余部分执行相同的操作。 这就是为什么递归函数可以帮助我们节省几行样板代码的原因: 递归解决方案 但是仅通过查看递归函数就可以肯定地说,我们获得的一行代码(与样板解决方案相比)不值得在递归调用中引入一致性和简单性的损失-请记住,并非所有开发人员对递归同样感到高兴。 简化的解决方案: 如果我告诉过您所有的样板代码和递归代码都可以限制为一行代码怎么办? 一个纯粹的面向对象的开发人员可能不会相信我,但是实际上,这是可以实现的。 如果考虑我们在做什么,我们将在递归数据结构上应用组合函数(distance(from :)),并以递归方式使用函数的每次应用结果。 这正是函数编程中高阶函数折叠所做的定义¹。 幸运的是,在Swift中,我们有一个类似的功能可以折叠: reduce(_:_:)函数reduce(_:_:) 。 reduce函数将初始结果和闭包作为参数,然后在返回最终结果之前使用闭包组合Sequence的每个元素。 最简单的示例是使用reduce函数对整数列表求和: [2,5,3,10] .reduce(0,+)//返回20 但是,在我们的情况下,我们需要更加具体,因为+函数实际上不适用于CLLocation对象。 相反,我们希望应用distance(from:)函数。 为此,我们还需要引用列表中的上一个(或下一个)元素。 reduce函数不会自动为您提供下一个元素的访问权限(与其他任何迭代一样),因此,为了解决此问题,我们可以使用元组作为初始累加结果,第一个元素是累加距离,第二个元素是累加距离先前的CLLocation对象: (CLLocationDistance, CLLocation?) 。 location元素是可选的,因为在我们提供给reduce函数的初始结果中没有先前的元素。 […]