Tag: swift

确定WKWebView的内容大小

本文最初发表在我的个人博客上。 我强烈建议在此处阅读该书,因为它可以更好地突出显示语法并提供阅读相关文章的建议。 在我最近的一个项目中,我不得不使用Web视图来显示带有本地CSS和自定义字体的HTML字符串。 Web视图必须与其他几个视图一起嵌入滚动视图中。 还必须将其高度调整为要显示的内容。 我的目标是创建以下内容: 我已经在以前的一个项目中做到了这一点,所以我想我会重用相同的代码。 问题在于代码使用的是UIWebView而不是较新的WKWebView 。 从iOS 8开始, UIWebView被功能更强大且结构更完善的WKWebView ,并且从iOS 12开始正式弃用UIWebView 。 这意味着我不得不重新实现该功能。 我已将所有代码放在GitHub上的示例项目中,以便您可以继续。 为了将HTML字符串加载到Web视图中, WKWebView具有loadHTMLString(_:baseURL:)方法。 我从后端获取的HTML字符串没有 , 和标记,因此我不得不手动添加它们。 加载HTML的方法如下所示: 重要笔记: 标签必须具有viewport元数据,这对于正确计算Web视图的内容高度非常重要。 baseURL中的baseURL参数必须是主要的捆绑包URL,因为我们将加载本地自定义字体。 在UIWebView本地CSS文件加载到HTML中非常容易。 您只需要在标记中添加 。 在WKWebView此过程有点复杂,因为它要求在HTML加载后注入CSS。 我们可以通过webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)的webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)方法来WKNavigationDelegate这WKNavigationDelegate : 首先,我们将style.css文件的内容加载到字符串变量中。 之后,我们使用JavaScript将标记注入Web视图的HTML。 这种方法的问题在于,Web视图将加载HTML并显示它,然后再应用CSS。 用户看不到该过渡,这是不好的。 幸运的是,有更好的方法。 我们可以使用WKUserScript来表示可以注入到网页中的脚本, WKUserContentController可以将脚本注入到Web视图中。 在WKWebView初始化期间,将在WKWebView内部使用这些对象: 使用这种方法,CSS将在HTML加载后立即加载,并且不会出现用户可以注意到的过渡。 要在Xcode中添加自定义字体,建议您遵循Apple的教程。 添加字体后,我们需要使用CSS将其加载到Web视图中。 要在CSS中使用自定义字体,我们需要使用@font-face CSS规则: […]

迅捷周:12.03〜12.16

静态与动态 在Swift中,我们偶尔会用到static这个关键字来让某个方法或属性被宣告成所谓的type方法或type属性。 medium.com swift中嵌套函数的实际用法是什么? 我认为您问题的核心是:为什么不使用私有函数而不是丑陋的嵌套函数? 简单的说… stackoverflow.com 从头开始Swift:函数参数,类型和嵌套 在上一篇文章中,我们探讨了Swift中的函数基础。 但是,功能还有很多。 在… code.tutsplus.com UICollectionView,全宽单元格,是否允许自动布局动态高度? 您正在寻找自动高度,并且还希望具有完整的宽度,因此无法同时使用两者… stackoverflow.com

功能性Swift:闭包{}

闭包是可以独立传递的功能块,可以在代码中传递和使用。 – 苹果 闭包可以从定义它们的上下文中捕获和存储对任何常量和变量的引用,因此称为闭包。 您可以将闭包视为一个没有自己名称的函数,并从其环境中捕获任何值。 函数和闭包是Swift中的一流对象 :您可以存储它们,将它们作为函数的参数传递,并像对待其他任何值或对象一样对待它们。 将闭包作为完成处理程序传递是许多API中的常见模式。 标准Swift库主要将闭包用于事件处理和回调。 函数是执行特定任务的独立代码块。 您为函数指定一个名称,该名称可以标识其功能,该名称用于“调用”该函数以在需要时执行其任务。 您可以使用func关键字定义一个函数。 函数可以不带太多参数,可变参数而返回任何一个或多个参数。 函数类型由参数类型和函数的返回类型组成。 对于上面的示例,函数类型为: (Int, Int) -> Int 可以将其理解为:“具有两个参数的函数,都具有Int类型,并且都返回Int类型的值。”可以将函数类型设置为参数或函数的返回类型。 可以将函数类型分配给任何这样的变量: var mathFunction:(Int,Int)-> Int =添加 函数是闭包的特殊情况。 闭包采用以下三种形式之一: 全局函数:它们具有名称,不能捕获值。 嵌套函数:它们有一个名称,可以从其封闭函数中捕获值。 闭包表达式:它们没有名称,可以从其周围的上下文中捕获值。 可以通过将函数类型放在大括号内并in返回类型后in关键字中来创建闭包。 单表达式闭包可以通过从声明中省略return关键字来隐式返回其单表达式的结果。 对于多行表达式闭包,不能省略return关键字。 如果由于函数的最后一个参数而需要将闭包表达式传递给函数并且闭包表达式太长,则可以将其写为尾随闭包。 在函数调用的括号()后面写一个结尾的闭包,即使它仍然是函数的参数。 使用尾随闭包语法时,不要在函数调用的过程中为闭包编写参数标签。 如果闭包是方法的最后一个参数,那么swift允许您这样编写: 使用reduce()的结尾封闭示例 尾随闭包语法的使用可以在闭包支持的功能之后立即整齐地封装闭包的功能,而无需将整个闭包包装在reduce(_:)方法的外部括号内。 闭包可以从定义它的周围上下文中捕获常量和变量。 然后,闭包可以从其主体内部引用和修改这些常量和变量的值,即使定义常量和变量的原始范围不再存在。 在Swift中,最简单的可以捕获值的闭包形式是嵌套函数,它写在另一个函数的主体内。 嵌套函数可以捕获其外部函数的任何自变量,还可以捕获在外部函数内定义的任何常量和变量。 Swift文档中给出的示例 此makeIncrementer函数接受一个参数(即Int)作为输入,并返回一个函数类型,即() -> Int 。 这意味着它将返回一个function ,而不是一个简单的值。 它返回的函数没有参数,并且每次调用都返回一个Int值。 在这里, amount是参数, runningTotal被声明为变量并初始化为0。嵌套函数incrementer runningTotal从周围的上下文中捕获amount和runningTotal […]

Swift 4中的iOS UIKit:调整UIImage的大小

预习 资源 项目 https://github.com/calmone/iOS-UIKit-component 参考 UIImage https://developer.apple.com/documentation/uikit/uiimage 快乐编码😄

Swift 4.0中的网络层

每当我开始一个新项目时,都会出现相同的问题。 如何实现网络层? 使用Moya,Alamofire等外部库或从头开始编写它。 我对这个问题的回答是–使用不带任何第三方库的纯Swift。 当然,实现面向协议的层非常简单,使用enum键入safe来配置端点并完全可测试。 在这几点中,您将学习如何编写可定制的面向协议的网络层。 在开始之前,了解URLSession及其组成类很重要。 通常, URLSession负责发送和接收HTTPRequests 。 对于基本请求,您可以使用没有配置对象的shared会话。 它不像您自己创建的会话那样可定制,但是如果您有非常有限的要求,它可以作为一个很好的起点。 对于其他类型的会话,您URLSession使用以下三种配置之一实例化URLSession : .default –会话表现为共享会话,但允许进行更多配置并使用委托增量获取数据。 .ephemeral –会话也类似于共享会话,但是不要将缓存,cookie或凭据写入磁盘。 .background –会话使您可以在应用程序未运行时在后台执行内容的上载和下载。 URLSession以两种方式返回数据: 完成处理程序 在委托上调用方法 在会话中,您可以创建URLSessionTask以从服务器检索数据,上传照片或下载文件。 此外,您还可以继续,暂停和取消任务。 URLSessionTask提供了暂停运行任务的机会,例如,当用户离开应用程序时暂停任务,并在返回时恢复任务。 URLSession提供三种类型的任务: data –使用Data对象发送和接收数据。 数据任务旨在向服务器发出简短的,经常是交互式的请求。 upload –与数据任务相似,但通常用于在应用程序不运行时上传文件并支持后台上传。 download –以文件形式检索数据,并在应用程序未运行时支持后台下载和上传。 在本教程中,您将仅使用第一种URLSessionTask来发送请求并处理服务器的响应。 简要回顾一下URLSession可以做什么URLSession ,现在让我们进行一些练习。 首先,您必须将网络层划分为小型服务。 将所有请求都保存在一个类/枚举中是很难维护的,并且可能会变成一个庞然大物。 ServiceProtocol将帮助创建URLRequest 。 ServiceProtocol包含构成组件,例如baseURL,路径,方法,标头,任务和parametersEncoding。 继续创建您的第一个简单网络层文件。 HTTPMethod是一个枚举,负责设置请求的HTTP方法。 URLRequest具有.httpMethod属性以设置方法的字符串类型。 Task是一个枚举,负责为特定服务配置参数。 您可以添加适用于您的网络层要求的情况。 例如upload(Data) , download(parameters: Parameters)等。该示例只有两种情况可以发送普通请求或带有参数。 ParametersEncoding是负责设置编码类型的枚举。 在此示例中,您必须使用最流行的:URL和JSON。 瞧! 创建网络层的第一部分已经完成。 […]

面试过程-第2部分-iOS问题

您好,欢迎阅读本系列的第2部分。 如果您还没有,请检出第1部分。 因此,对于本文,我从列表中选择了10个随机(简单)问题,以下是他们的答案。 1. 自我介绍 这里没有太多解释。 您只需要谈论您的专业经验,教育背景和家庭背景即可。 因此,以下是您在简介中应涵盖的要点 · 教育背景 -新生应该在您的简介中包括此内容,因为您没有太多要谈论的经验,但是有多年经验的人可以避免这样做,因为他们可以直接谈论他们所做的工作。 · 家庭背景 –根据我的看法,这是可选的,您可以从介绍中忽略,除非并且直到您认为面试官应该知道一些非常有趣的事情为止。 · 专业经验 –经验丰富的专业人员应包括以下几点 · 多年经验。 ·当前/最后一家公司。 ·当前/上一个项目。 根据我的介绍,我仅介绍了一些重要的内容。 这仅是准则,而不是您必须遵循的规则列表。 如果您已经准备好一个经过充分准备和排练的介绍,那么使用它就不会有任何问题。 2. 完成最具挑战性的任务。 这是一个棘手的问题,您应该始终为该问题准备一个答案,因为如果尝试在面试中解决这个问题,那么在大多数情况下,您会想到的答案要么太简单,要么太难解释。 因此,最好对此问题准备充分的答案。 3. 列举一些您曾经使用过的iOS框架 这又是您应该事先准备的东西。 我一直在问这个问题,而我只记得UIKit 🤦🏽‍🤦🏽️。 我并不是说所有人都会发生这种情况,但事前准备没错。 4. 最新版本的swift中引入的新功能 每个新版本的swift都会引入新的变化,您应该知道这些变化。 您可以阅读或观看视频以保持最新状态。 您也可以参考whatsnewinswift网站。 在这里,您可以根据引入的所有swift版本跟踪swift中引入的所有更改。 5. 什么是闭包,它们是引用类型还是值类型? 我敢肯定,您中的许多人都使用过闭包,但是如果有人要求您定义或解释闭包,那么它将变得有些困难。 知道一件事是一回事,用正确的单词正确地解释它是另一回事,对吗? 无论如何根据迅速的文档 闭包是可以独立传递的功能块,可以在代码中传递和使用。 Swift中的闭包类似于C和Objective-C中的块,以及其他编程语言中的lambda。 因此,您可以使用以上定义来解释采访中的闭包。 对于问题的第二部分, 闭包是引用类型 。 请同时阅读以下主题(上述快速文档超链接中的详细信息)。 ·闭包的类型,即转义和不转义 ·尾随封口 ·自动完成关闭 […]

对不起,您睡过三角法了吗? 你将会。

在我所有的数学课程中,从代数到几何再到微积分,三角学始终是事后的想法。 真可惜,因为当我听到有人说“数学在现实生活中从来没有帮助过我!”时,我立即认为那仅仅是因为他们不记得自己的三角学。 我很幸运地拥有一位非常热衷于让我了解Trig,尤其是Unit Circle的导师,即使我不记得所有可用的东西,我也永远会记住这个经常变化的数学领域有多么宝贵。 三角函数是一个非常简单的名字的奇特名字:将圆分成多个角度。 关于圆的令人敬畏的事情是:1)它在整个表面上是连续的,并且2)它控制可能的角度的整个范围。 我们将这两种性质放在一起,得到基本的三角函数。 因此,了解三角学的基本单位是单位圆,这就是我们要开始的地方。 这里有单位圆。 它看起来确实很复杂,但实际上您需要记住的是,它只是一个划分为基本角度的圆。 我们的操作方法如下:我们知道一个圆的周长为2π,因此将圆分成虚数部分,称为弧度,而在圆中有2π。 假设我们对角度有所了解,您可以说我们有一些简单的弧度值,只需将弧度的总和减半即可将其转换为角度: 一直绕圆-将其视为360度-2π弧度 绕圆的一半-这是180度-π弧度 再说一半,即四分之一圆-这是90度-π/ 2弧度 最后四分之一的一半(45度)为π/ 4弧度 所以减半很棒,但是我们如何获得其他重要角度,或者如何获得所需的任何角度? 好吧,我想做的是相对于90度旋转。 如果我想要30度,那我知道那是90度的1/3。 不好了! 现在我们必须除分数! 我曾经讨厌这个,但如今我知道这没什么大不了的。 就像π/ 2的一半是π/ 4,π/ 2的1/3(记住是90度)是π/ 6。 所以现在我们可以从这里得到想要的任何角度,只要是90的偶数倍即可: 记得! 90度是π/ 2弧度。 30度:π/ 6弧度(30进入90 3倍,如π/ 2的1/3所述为π/ 6) 10度:π/ 18弧度(因为10进入30 3倍) 1度:π/ 180弧度 哇! 看看那个最后一个家伙! 我们怎么到那里? 好吧,请记住180度是π弧度……我们知道我们可以将任意个数除以1,因此,如果将π弧度除以180,则1度必须是π/ 180弧度! 现在我们可以将任何角度转换为弧度! 只需取所需的度数,然后乘以分数π/ 180即可! 如果您因担心数学而瘫痪,甚至不需要减少! (恭喜!:) 我的想象力受损的读者说:“嘿,等等!这不是Swift博客吗? 这如何适用于Swift? […]

合理,类型安全且灵活的实现,用于管理Swift App中的错误

上周,我开始重构一些与我现在正在使用的应用程序内的错误管理有关的代码。 我试图在互联网上找到一些实现示例,但是没有运气。 这就是为什么我在这里介绍自己的原因。 错误架构 在大多数情况下,应用程序仅用作前端,以向用户呈现信息。 因此,它与为它提供所需服务和数据的不同实体进行交互。 该实体是例如在线API,本地数据库或第三方框架。 他们所有人都会遇到错误。 我们应用程序的目标是捕获它们并做出相应反应,并在必要时通知用户。 为此,通常将错误与唯一的域ID(通常是字符串)和该域内的唯一代码(通常是整数)相关联,以识别错误。 因此错误架构如下所示: 在大多数情况下,错误还将包含其他关联数据,例如,如果发生错误,您将需要向用户显示本地化描述。 那么,您如何将所有这些信息反映到实现中? 更重要的是,如何使实施易于使用,组织合理,灵活且类型安全? 此外,最好在每个错误域内保修唯一的错误代码,并在编译时在我们的应用程序内保修唯一的域ID 。 一,错误的最低要求 我们可以使用协议指定它们: 我们还可以扩展该协议并添加一些有用的东西: 因为我们将使用具有原始整数值的枚举,所以我们添加了初始化程序和code属性的默认实现。 我们还添加了domain属性,因此我们可以访问错误的域ID,而无需访问其封闭类型(我们在协议中将其声明为静态)。 二,用于存储错误信息的类型 枚举类型是为此目的。 它还允许将原始值链接到每种情况,并保证此原始值是唯一的。 它们是存储错误代码的理想选择。 与ErrorProtocol一起,我们实现了一个基本错误,该错误在编译时为每个域强制使用唯一的错误代码。 域ID不能保证是唯一的(我没有在Swift语言中找到在编译时强制执行的工具)。 三,组织代码 为了组织代码,我选择镜像错误体系结构。 使用嵌套类型,我创建了一个伞形类型,用于存储所有不同的错误枚举(每个枚举与一个错误域匹配): 四,伞型的要求 给定一个域和一个代码,每种包装对应于多个错误域的枚举的伞型都应该能够返回错误。 我们可以通过使伞形类型符合以下协议来获得此功能: 在这种情况下,匹配函数负责探索伞型下每个枚举的域ID,并返回与域和代码匹配的错误。 由于Swift是一种类型安全的语言,因此我们需要为所有包含的枚举指定通用类型。 我们可以通过使用非通用协议作为具体类型来实现。 所有封闭的枚举都应符合此协议以及ErrorProtocol。 真实的例子 让我们看一个真实的例子。 现在,我正在一个名为AVO的应用程序中使用此实现(因此,如果您在即将发布的代码中看到AVO,现在您知道原因了)。 首先,我创建了一个满足我的需求的错误协议,该协议继承自ErrorProtocol并包含错误的本地化描述: 其次,我创建了一个伞形类型来存储所有错误枚举。 我使它符合ErrorUmbrellaProtocol并实现匹配功能: 然后添加错误枚举(在这种情况下为两个域,即内部应用程序错误和服务器错误): 现在我们可以如下使用所有这些。 例如,假设我们从服务器获取域ID和错误代码: 为了检查我们收到的确切错误,(如果您要做的不只是显示本地化的错误说明,还可以通过几种方法来做到这一点: 而且将错误信息发送到应用之外也非常容易: 干净吗? ^^

TVML和UIKit作为快乐的室友

每个tvOS教程都有一个经典的开始,这是一个问题:您要创建TVKit应用程序还是本机UIKit应用程序? 根据该问题的答案,您将获得两种完全不同的创建应用程序的方法之一。 关键是该问题的答案通常不是那么容易,因为实际上,TVKit或UIKit两种选择都有其优点和缺点。 📺TVKit :是快速原型制作的绝佳解决方案。 Apple提供了一套非常漂亮的TVML模板 ,因此只需几行代码,您就可以得到外观精美,与系统完全集成的应用程序。 另一方面,TVML模板基本上就像它们一样,并且确实提供了相当低的自定义级别。 💄UIKit :另一方面,提供了更高级别的定制。 但是它缺少那些精美的模板,因此您需要手动创建所有所需内容。 如果我们可以将它们混合起来,那不是很好吗? 因此,我们可以同时拥有一个非常可定制的App,并可以选择使用TVML快速制作特定部分的原型吗? 分离式TVML: 开始使用TVML的必要步骤之一是设置TVApplicationController的实例。 TVApplicationController的这一实例将使我们能够将应用程序的控件发送给JS。 通常,TVML Apps直接在其AppDelegate中创建其TVApplicationController实例,这基本上就是它们具有的所有快速代码: 如您所见,TVApplicationController的构造函数接收的参数之一是应用程序窗口。 关键是,当将该窗口参数设置为我们的TVApplicationController时,它将实际上将应用程序的rootViewController设置为我们的TVKit代码定义的那个。 但是,如果那时我们不将TVApplicationController的实例绑定到窗口,而是使用nil代替window参数,该怎么办? 然后,我们将获得未绑定到窗口的TVApplicationController的分离实例。 还要感谢TVApplicationController公开的属性navigationController ,它只是一个标准的UINavigationController,我们可以根据需要手动托管它。 这是一个非常简单的示例,当触发IBAction sendMeToTVMLButtonWasPressed时,UIKit ViewController呈现TVKit屏幕: 就是这样,通过这种简单的方法,我们可以在同一App中使用UIKit和TVKit,并在它们适合时使用它们中的一个。 TVML作为UIViewController: 注意到使用UIKit或TVKit实现视图只是实现细节这一事实,如果我们能够摆脱那些具有相似接口的特殊性,那不是很好吗? 实际上,这就是我们可以将TVKit代码嵌入UIKit容器视图中的内容,因此它通过UIViewController的界面公开。 给我看代码: 如果您对此感兴趣,请准备一个结合了UIKit和TVKit的简单项目,将TVML屏幕嵌入UIKit ViewController中,以便像其他任何ViewController一样呈现。 让tvmlViewController = TVMLViewController() 存在(tvmlViewController,动画:true,完成:nil) 只是为了好玩……我还向TVKit屏幕添加了一些JS,并将其与Swift中的一些异步代码绑定以模拟一些网络通信。 结论: UIKit很棒,自那以后一直存在,一直为我们提供许多强大和灵活的功能,但是无论您是否喜欢,Apple都在TVKit和这种新的工作方式上投入了大量资金。 最好的部分是TVKit和UIKit绝对不是排他性的,我们可以在需要它们时利用它们各自的优点进行混合。 如有任何疑问,请随时在github , twitter或dcordero.me上添加我。

工业视图:矢量化视图

今天的iOS建筑工人食谱:如何使用通过PaintCode创建的自定义UIView在iOS项目中“矢量化”一个以太坊图标文件。 在适当的情况下使用,在代码中绘画一些图标将使该项目更加敏捷,更加幸福,并与世界全面实现精神和情感上的和平。 问题 在日常的工业iOS工作中,开发人员会为iOS应用遇到很多图像。 通常这些文件打包为PNG或JPG文件,因此随着时间的推移,该项目最终会产生数十个图像文件。 有时,您的设计师会要求您对图标进行颜色或大小上的细微调整,而来回剥离图像文件可能会很累。 尽管有很多出色的工具(Zeplin,Sketch等),但手动将图像文件一次又一次地添加到Xcode中并造成潜在的合并冲突总是很麻烦的。 解 使用PaintCode创建自定义UIView,它将始终绘制您需要的所有变体,所有A / B测试组合。 是的 图标最适合绘图吗? 我上线了,从jax gotham找到了一组50个以太坊图标,可以在SVG中使用,并且是开源的……谢谢Jax! 通常,当图标没有太多点并且很容易调整大小时,它们非常适合这种矢量化的UIView。 只需将ethereum-coin3.svg拖到PaintCode中,它就会在下面的代码翻译中显示,非常好! 正如Caroline Begbie所指出的那样,PaintCode还是学习iOS(和其他平台)上Core Graphics和UIKit上绘图的一种好方法。 我对这些层进行了分组和调整,以便以后可以在代码中对其进行自定义。 自定义颜色,然后将它们分配给特定的组以供以后自定义也是一个好主意。 调整大小限制功能是PaintCode最好的功能之一。 您只需要对元素进行分组,然后将它们放置在框架下-这将使图标随框架正确调整大小。 您可以从PaintCode的代码菜单中复制和调整代码,也可以将其导出为StyleKit:此StyleKit可以包含多个图标和自定义颜色的绘图代码。 一旦在Xcode中提供了CryptoCoin样式包,就可以很容易地对代码进行调整,以执行基本的工作,例如为每个组设置颜色(完整代码): 公共 类 CryptoCoin:NSObject { @objc 动态 公共 类 func drawEthereumcoin3(frame:CGRect = CGRect(x:0,y:0,宽度:1024,高度:1024), coinColor:UIColor = .white, outlineColor:UIColor = .black, logoColor:UIColor = .black, gleamColor:UIColor = .black){ /// 以太坊硬币视图 这是日常使用的原始模板,以及用于日常情况的默认初始化器。 就是这样! 现在,您已经有了一个不错的UIView类,可以随时用于工业化日常使用: […]