Tag: swift

快速浏览类型擦除

如果您正在编写Swift,那么您可能已经听说过类型擦除。 也许您甚至在使用它。 但是,即使您属于这两个阵营中的一个,也有可能实际上不知道为什么类型擦除有效。 ♂️ 与其给您提供有关如何擦除类型的方法,不如让我们实际研究问题所在并逐步解决。 问题 假设我们正在制作一个通用网络会话类,该类必须支持各种JSON反序列化器,这些反序列化器返回的对象与网络会话的关联类型匹配。 像这样: 这很烦人,但确实有道理。 我们的协议JsonDeserializer是抽象类型,因此Swift编译器无法推断其引用的具体类型,也不能假设其在编译时由其associatedtype提供的类型。 Hector Matos在他的博客KrakenDev : 简短的答案是:Swift希望是类型安全的。 再加上它是一种提前编译的语言,并且您有一种需要NEEDS能够在编译期间随时推断具体类型的语言。 我不能太强调。 在编译时,不是函数/类约束的每个类型都需要具体。 协议中的关联类型是抽象的。 这意味着它们不是具体的。 他们是假的。 没有人喜欢假货。 因此,尽管此错误令人不快,但确实有道理-并且该错误告诉我们一些重要的信息。 指出,该协议只能用作通用约束 ,即在尖括号之间。 尝试1 我们知道,将JsonDeserializer用作类型约束的唯一方法是在使用它,但是出于参数的考虑,我们决定使用协议约束来指定一种类型,就像我们对泛型类的处理方式一样。 结果如何? Cannot specialize non-generic type ‘JsonDeserializer’ ❌ 虽然这是预期的。 正如我们前面所讨论的,该协议是一种抽象类型,尽管它可能具有通用要求,但它本身并不是通用类型。 不是class SomeType { … }方式。 尝试2 好吧,让我们尝试使用JsonDeserializer作为一般约束,并将反序列化器放入一个代理对象,我们将其称为DeserializerBox (此处使用Box是为了与以后的类型擦除命名约定保持一致)。 这个错误告诉我们我们需要提供一种类型来满足DeserializerBox的通用类型要求。 不幸的是,这意味着要指定一个JsonDeserializer 。 但是,我们想使用任何为我们提供Payload类型对象的JsonDeserializer ,因此指定特定的反序列化器具体类型将无法达到目的。 这与仅将具体类型用作Session的deserializer属性的类型约束没有什么不同。 令人沮丧的是,这是进步。 尝试3和3.5ish 为了弥补我们缺乏必要的类型争论,我们还需要DeserializerBox成为JsonDeserializer的真正代理对象,这意味着它应与JsonDeserializer 。 这意味着我们应该能够将代理与JsonDeserializer一样对待,并且它应该公开相同的接口。 为此,我们必须坚持使用JsonDeserializer […]

Xcode 10的构建系统和代码生成(R.swift)

Xcode 10包括一个默认启用的新构建系统,该系统可提高构建性能。 这是非常令人欢迎的改进。 R.swift是一个开放源代码库,它使使用图像,字体和segues之类的资源变得更加容易且类型安全。 这是一个非常酷的库,我们已经在Zendesk上成功使用了一段时间。 然而… 当构建使用R.swift和Xcode 10的项目时,构建将失败,并出现以下错误: 错误:找不到构建输入文件:/LOCATION/R.genic.swift R.swift使用Xcode构建脚本阶段集成到项目中。 此阶段生成一个Swift文件R.generated.swift ,该文件在构建项目时进行编译。 生成失败,因为具有新的并行生成系统的Xcode 10试图在创建R.generated.swift文件之前先找到它。 Xcode 10允许我们为构建脚本阶段指定输出文件。 我们可以将R.generated.swift文件添加为输出文件,如下所示: 这样可以成功构建。 太棒了! 🎉 额外 最初遇到此问题时,我们使用R.swift打开了一个错误。 但是,如上所示,该问题是由于Xcode的构建系统中的更改引起的。 而已! 📱🚀👍🏽 也可以在petethedeveloper.com上获得

UIKit:查看阴影

上次我们讨论了如何使视图的角变圆。 今天,按照承诺,我将向您展示如何使用layer.shadowX属性,以使视图看起来像Card,并获得其他炫酷效果。 让我们从简单而永不过时的Card View开始。 我知道你需要这个 myCard.layer.cornerRadius = 10 myCard.layer.shadowOpacity = 1 myCard.layer.shadowColor = UIColor(名称:“ Swift Orange”)!. cgColor myCard.layer.shadowRadius = 4 myCard.layer.shadowOffset = CGSize(宽度:4,高度:4) 该代码是不言自明的: 我按照上cornerRadius UIKit Rounded Views中的描述设置了cornerRadius属性。 我将阴影不透明度设置为从0到1的值,以将其应用于阴影颜色。 我设置阴影颜色。 我设置代表模糊半径的阴影半径。 如果您不愿意像我一样阅读,则只需要知道该值越高,图像就会越模糊。 如果您想学习,请单击此处。 最后,我设置偏移量,该偏移量是阴影相对于以点表示的图层的偏移量。 注意:要使阴影可见,请不要将layer的属性masksToBounds设置为true,否则它将被裁剪。 这还没有结束……还有一个阴影属性可供我们使用,以产生一些很酷的效果: shadowPath。 让我们看看如何制作一个像漂浮在设备屏幕上的视图。 让cardWidth = myCard.frame.width 让cardHeight = myCard.frame.height 让distanceFromCard = 15 myCard.layer.cornerRadius = cardWidth * 0.5 myCard.layer.shadowOpacity = 0.1 […]

数据结构(基础知识)

数据结构是解决算法问题的有用工具。 您可能熟悉的两个数据结构是数组和字典。 数组具有内置的函数,可让您解决问题。 您可以对数组进行计数,对数组进行排序,将项目追加到数组中,在数组中的项目之间循环等等。类似地,您可以将键值对插入字典中,从字典中提取键值对,等等。 ,队列和树是另外三个对您的代码工具箱有用的数据结构。 堆栈 堆栈有助于按特定顺序组织数据。 堆栈可归为三大功能: 推动将新元素添加到堆栈顶部 弹出以从堆栈顶部删除元素 窥视堆栈顶部而不弹出 与您放在桌上的一堆纸类似,添加到纸堆中的最后一个元素是可以从纸堆中删除的第一个元素。 另外,就像您只能看到桌子上纸叠顶部的纸上内容一样,您也只能看到编码纸叠中的顶部元素。 如果使用字符串,上面的示例很好,但是如果要使用其他类型,该怎么办? 没有恐惧! 泛型在这里! 使用泛型堆栈 s列 类似于堆栈,队列有助于按特定顺序组织数据。 与邮局在队列中等待的第一个人是第一个离开队列并得到服务的人一样,代码队列中的第一个元素也是第一个离开队列的元素。 队列可归为三大功能: 排队将新元素添加到队列 出队以从队列中删除元素 偷看队列中的第一个元素而不将其从队列中删除 像堆栈一样,您也可以将泛型与队列一起使用。 树木 树有助于提高搜索效率,提供排序的数据列表以及使对象之间具有层次关系。 树木由三个元素组成: 节点是树结构中的数据块 根是树的入口点(零级节点) 叶子 (终端节点)是没有子节点的节点 由于树是由节点组成的,因此我首先创建一个Node类。 此类由值,Node类型的子级数组(有时还包括Node类型的父级)组成。 您可能想知道为什么我指定Node类符合等于协议。 为了在使用泛型时实现搜索功能,我不得不让Xcode知道Node类实际上可以执行比较。 如果您要以树的方式考虑上述测试,它看起来像这样: 您可能已经听说过专门的“二叉树”。二叉树是其中每个节点只有0,1或2个子节点的树。 二叉搜索树是一棵树,它从树中插入和删除信息,以便始终对树进行排序。 要了解更多信息,请查看以下链接: 二叉树 二进制搜索树 参考文献: https://github.com/raywenderlich/swift-algorithm-club

SKStoreReviewController — Apple在ios 10.3及更高版本中的iOS应用中请求评论和评级的方式

每个应用程序开发人员的目的都是为了获取反馈或对其应用程序进行评论,以更好地展示其应用并鼓励其他人使用他们的应用程序。 通常,开发人员会向其应用程序提供自定义评论UIView以及UIStackview中的星图。 然后,将用户评分记录在后端中,但在进行应用商店评论时,用户通常会说“现在不选择”选项,因为该用户将从当前应用程序的屏幕中退出,进入Apple App Store页面。 我们是否因为这种行为而错过了用户的反馈? 苹果推出了“ SKStoreReviewController”,可在您的应用程序屏幕上显示评论UIView,并记录评论和评论。 无需任何用户导航到Apple应用商店即可提交他/她的评论。 凉。 是不是 三个简单步骤是: 导入StoreKit。 检查版本是否为10.3及更高版本。 if #available(iOS 10.3, *) { //call ios API method for review view. } else { //Use your custom review view. } 从视图控制器调用SKStoreReviewController.requestReview()。 if #available(iOS 10.3, *) { SKStoreReviewController.requestReview() } else { //Use your custom review view. } 多田! 系统将为您提供评论视图和星号,以对应用程序进行评级。 很好,但是在实现“ SKStoreReviewController”视图时,我们必须意识到某些要点。 […]

自定义导航栏

您知道您可以自定义导航栏吗? 我们开始做吧。 很简单 创建一个新项目。 转到情节提要。 单击ViewController。 转到“ 编辑器->嵌入->导航控制器 ”。 因此,创建了一个导航栏。 现在添加两个条形按钮。 将图像添加到您要显示在导航栏中的Assets.xcassets文件夹中。 现在开始编码。 转到ViewController.swift。 编写一个新的函数覆盖func viewDidAppear(animated:Bool)。 然后将此代码添加到函数中: 现在,让我们逐行浏览代码。 初始化导航栏。 定义导航栏的样式。 设置条形按钮的颜色。 初始化imageView,所以我们有一个显示图像的地方。 创建一个图像并将其设置为我们的imageView。 将imageView添加到我们的导航栏中。 做完了 运行项目 您的导航栏是自定义的。 超级容易。 参考文献: Главнаястраница

Server Side Swift入门:1.1

Turnstile SQLite演示 欢迎来到我的“ Server Side Swift入门”系列的第二部分。 在整个系列文章中,我将解释如何使用Perfect工具箱使用Server Side Siwft的各个不同方面进行入门和运行的基础知识。 本文演示了如何运行Turnstile SQLite演示并探索其Web路由和API,以及深入研究SQLite数据库并找出导致会话滴答的原因。 Turnstile是Stormpath构建的身份验证过程,其模仿Apache Shiro。 Perfect已将其作为该项目的身份验证选项之一,并带有SQLite,MySQL,CouchDB,PostgreSQL和MongoDB的驱动程序。 SQLite是一个出色的教学数据库工具,因为它基于文件,并且几乎不需要任何设置,并且所有Mac和大多数Linux系统都将SQLite作为标准配置。 但是,我不建议在大规模生产系统中使用它。 首先,如果您尚未获得Perfect Assistant应用程序,请访问https://www.perfect.org/en/assistant/以下载Perfect Assistant。 在“欢迎”屏幕上,单击“创建新项目”按钮。 这将滑落为两种项目类型的工作表。 在“示例”下,选择“完美:带有SQLite的旋转门”。 使用“浏览按钮”选择应用程序的位置-并根据需要创建一个新文件夹。 请注意,在Perfect Assistant中,“项目名称”是您选择的文件夹的名称。 取消选中“将Linux构建与Xcode项目集成”,因为在本演练中我们不会部署到Linux。 按下“保存”后,Perfect Assistant将继续创建项目,下载所有依赖项并创建Xcode项目文件。 完成后,您的项目也将列在左侧的“项目”列表中。 它向您显示了项目中已经存在的依赖关系-如果您没有看到自己认为应该存在的内容,请不要担心,子依赖关系也会自动包含在内。 从这里,您还可以在查找器或终端窗口中打开项目目录,然后打开Xcode项目。 在Xcode中,打开Sources目录,您将看到许多其他依赖项已自动添加到我们的项目中。 添加这些是因为它们是子依赖项。 在我们的项目源目录中是一个main.swift文件。 这包含用于运行演示的代码。 需要指出的几件事。 在第38行,我们在此处定义SQLite数据库文件的位置-SQLiteConnector.db属性设置为“ ./authdb”。 SQLiteConnector.db =“ ./authdb” 因为SQLite是基于文件的数据库,所以我们可以将文件放置在所需的任何位置,但是在这种情况下,我们告诉应用程序将其放置在运行时工作目录中。 您还将在项目浏览器中注意到,我们有一个名为“ webroot”的目录。 这是我们保留CSS,JavaScript和图像之类的静态资产以及胡子模板的地方,我们将在本系列的另一部分中介绍这些模板。 由于存在诸如SQLite数据库和webroot目录之类的文件,因此我们需要告诉Xcode在何处考虑“工作目录”。 在“方案”下拉列表中,确保选择“具有终端外观”的黑色图标,并确保目标是“我的Mac”。 现在,让我们选择“编辑方案”。 在“运行->选项”选项卡中,确保选中“工作目录”选项,然后单击文本输入区域中的“文件夹”图标并导航到项目的目录。 在这里,您将看到“ Sources”目录和“ webroot”。 现在可以运行项目-按下三角形的“运行”按钮,或在键盘上按下CMD-R。 构建完成后,Xcode将执行该应用程序,并在右下侧控制台视图中显示一条消息,表明它已在端口8181上启动HTTP服务器。 [INFO]运行设置:用户 […]

地理栅栏:如何使用Swift在现实世界中实现虚拟边界?

什么是地理围栏? 地理围栏是一种定义现实世界地理区域周围的虚拟边界的技术。 每次用户进入或退出某个地理围栏的边界时,都可以在支持位置的设备(通常是智能手机)中触发动作。 通常,用户将根据其位置实时接收包含某些信息的通知。 这项技术的主要优势在于,它将虚拟世界与真实世界融合在一起。 在横向视图中,我们在多个项目中利用了地理围栏,特别是在卫生行业。 地理围栏在移动开发中的应用 地理围栏可以有多种应用程序: 市场营销 :服装店附近时,服装店可以通过当天的优惠和折扣触发推送通知。 提醒 :此应用程序可以提醒足球俱乐部的球迷在周围时进入体育场的大门的地址。 到达和离开特定位置:航空公司可以发送通知,希望用户在飞机起飞后安全旅行,或者在飞机降落时发送欢迎消息。 儿童追踪 :应用程式可以传送通知,告知父母其子女已离开或进入特定区域。 安全性:进入或离开区域时,该应用可以启用或禁用功能。 但是,地理围栏并不是要随身携带推送通知轰炸用户。 重要的是要向用户提供相关信息,以便在正确的时刻考虑到用户的需求,从而做出更好的决策。地理围栏的目的是增加价值并为客户提供更好的体验。 相应地使用它,将为客户和企业创造双赢局面。 因此,了解这种技术的强大功能的重要性。 优点 通过提供实时报价,折扣和促销来吸引客户。 增强用户体验。 向用户发送位置特定的通知。 缺点 地理围栏需要用户的批准。 如果用户拒绝或禁用位置服务,则必须在应用设置中启用地理围栏,然后才能使用。 位置跟踪会消耗过多的电池电量,这是用户关闭设备中的位置服务的首要原因。 仅适用于大范围区域。 知名应用中的地理围栏 您是否曾经问过自己,当您在已经访问过并签到过的地方附近时,Foursquare会如何向您发送提醒? 或《 Pokemon-Go》如何在关键区域禁用狩猎小精灵? 答案是地理围栏:在现实世界中创建边界,同时通过移动设备跟踪您的位置。

基于Texture的聊天应用程序

Texture를이용한ChatKit만들었다。 정말기능만 。다른이브러리들도해봤었다。 mukyasa / MMTextureChat MMTextureChat –用于 Whatsapp 和iMessage的 AsyncDisplayKit (Texture)平滑滚动聊天模拟 github.com MessageKit /消息包 MessageKit –开发中:JSQMessagesViewController社区驱动的替代品 github.com nguyenhuy / AsyncMessagesViewController AsyncMessagesViewController –适用于iOS的平滑,响应和灵活的消息UI库。 github.com slackhq / SlackTextViewController SlackTextViewController –带有不断增长的文本输入视图和其他有用消息传递的嵌入式UIViewController子类…… github.com 생각한이있었는데,내가생각한聊天应用程序라이브러리에서가핵심적인능은 追加,追加용이해야한다。 前置스때유이유지되야하고사용자좋아야한이좋아야한다。 消息输入UI를이기가용이해야한다。 Diff算法Diff算法,网络,网络,网络和应用程序。 聊天应用程序능들과기부부가적으로능들기능들이많다。 GTChatKit产品和服务GTGhatKit产品。 용법을먼저먼저 class기子类 类ChatNodeController:GTChatNodeController {…} 请参见GTChatNodeController子类。 그냥리。이같初始化그냥이다。 让viewController = ChatNodeController() 그리고가능한로퍼티자면보자면보간단히 类ChatNodeController:GTChatNodeController { … func foo(){ let collectionView = […]

在iOS上使用MVVM进行路由

我在多个项目中使用MVVM已有一段时间了,我非常喜欢它的简单性。 特别是,如果您像许多人一样从MVC移出,则只需要在体系结构中增加一层即可; 查看模型。 如果您发现太多复杂的图层,这确实使事情变得容易。 这是一个好的开始,但是这种简单性并不总是很好。 在MVVM中,将业务逻辑移出视图控制器(VC),然后意识到它仍然很胖。 视图模型(VM)现在具有业务逻辑,但是表示数据(格式)或路由又如何呢? 它们仍然停留在VC中,我们需要将它们移出。 样品流量 假设我们正在实现一个登录屏幕,如下所示。 路线清单: 登录>主屏幕 注册>注册屏幕 忘记密码(?)>忘记密码屏幕 这似乎是一个简单的屏幕,可以使用带有3个脚本的情节提要实现。 但是请相信我,事实并非如此。 例如,您通常会在登录时打开主屏幕。 但是在这种情况下,用户的密码可能已过期,您需要实现重定向以更改密码屏幕。 因此,登录路径变为: 登录>主屏幕或更改密码屏幕 这是情节提要路由失败的地方。 它只是无法应付这种动力。 因此,通常要做的就是让VC处理它: func loginButtonTapped(){ //开始网络请求… //回应后: 如果viewModel.shouldChangePassword { performSegue(id:“ ChangePasswordScreen”,发送者:nil) }其他{ performSegue(id:“ HomeScreen”,发送者:nil) } } 这是路由逻辑,不应在VC中使用。 如果要使用轻量级VC,请在编写if语句之前三思。 他们是决定,不属于那里。 以我的理解,VC仅应具有与视图相关的代码和粘合代码。 永远没有决定。 让我们定义一个路由器协议,并将这些if语句从VC中删除。 我们会需要: 路由ID :字符串标识符,例如segue ID。 上下文 :要从其路由的当前视图控制器。 可选参数 :过渡所需的临时数据。 (点击的行索引等) 协议路由器{ 功能路线( 到routeID:字符串, 来自上下文:UIViewController, […]