Tag: swift

如何从NSTokenField删除令牌? [迅速4.2]

在过去的几天中,我花费了大量时间正确地实现了具有某些拖放功能的标准NSTokenField。 知道了这一点,我们可以检查objectValue对象的类型是否等于我们期望的代表对象的类型。 如果确实如此,我们知道我们需要删除整个令牌。 然后,我们通过将stringValue拆分为一个数组并将其与objectValue中的对象数进行比较来检查对象数。 如果让 anyObjectsArray = control.objectValue 作为 ? [ 任何 ], 让 tokenFieldObjects = anyObjectsArray 为 ? [标签] { //现在,我们继续删除令牌… 让 stringObjectComponents = control.stringValue.split(separator:“,”) //检查令牌数是否等于tokenField的stringValue中的对象 如果 tokenFieldObjects.count == stringObjectComponents.count { //接下来,找出要删除的对象 } } 我们确信,我们必须删除令牌。 但是,在此阶段,我们不知道必须删除哪个令牌或多少个令牌。 幸运的是,找到它相对容易(当您知道时)。 如何找出要删除的令牌? 实例方法control(_:textView:doCommandBy :)还提供了NSTextView,如果您想找出光标在令牌字段中的位置,该类非常方便。 NSTextView有一个名为rangeForUserTextChange的方法,该方法返回一个NSRange,该NSRange由位置和长度组成。 var textChangeLocation = textView.rangeForUserTextChange.location 让 textChangeLength = textView.rangeForUserTextChange.length 我们暂时忽略长度 (稍后再讨论),并专注于location 。 我们只需要检查位置是否少于对象数。 如果是的话,我们需要将其减少1以获取对象在数组中的索引,因为数组的索引为零,而NSRange从1开始。 […]

如何在Swift Cocoa Touch框架中添加Objective-C文件

这篇文章是了解如何在Swift Cocoa Touch Framework项目中的Objective-C中添加第三个 库或文件的提示。 三个简单的步骤,让我们开始吧! 步骤1 首先要做的是在项目内部添加 Objective-C文件 (可以拖放) 。 第2步 将文件放入项目后,必须进入“ 项目目标” ->“ 构建阶段” ->“ 标题” 。 在“ 项目”选项卡中将看到所有“ .h”文件。 您必须将所有文件拖放到“ 公共”选项卡。 见下面: 现在,所有“ .h”文件都是您项目中的公共文件。 使它们可用是另一件事。 第三步 最后要做的是将它们导入 Bridge文件(由Xcode自动创建)。 桥通常是扩展名为“ .h”的项目的名称 。 注意 :如果项目名为 MyProject ,则Bridge文件的名称将为MyProject.h 。 打开Bridge文件,然后在导入中添加项目中的所有Objective-C标头。 #import #import “SomeImportedFile.h” 做完了! 现在所有项目都可以在Swift文件中使用那些Objective-C文件了。 谢谢!

使用UIEdgeInsets布局UIButton

您可以使用插图来布局系统或自定义按钮的内容。 通过插入,您可以为按钮的标题( titleEdgeInsets ),图像( imageEdgeInsets )以及标题和图像( contentEdgeInsets )一起添加或删除空间。 要查看这三个属性的工作原理,请通过xib文件或创建一个按钮( UIButton ) 在代码中。 在超级视图约束中,仅在垂直和水平方向上给它一个中心,在第一个示例中,不给它一个宽度上的约束。 为contentView提供蓝色背景色,为imageView提供红色背景色,为titleLabel提供黄色背景色。 最重要的是,您还可以为按钮的边框赋予绿色。 button.backgroundColor = .blue button.imageView?.backgroundColor = .red button.titleLabel?.backgroundColor = .yellow button.layer.borderColor = UIColor.green.cgColor button.layer.borderWidth = 2 contentEdgeInsets的行为符合您的预期。 您可以使用正值在imageView和titleLabel周围添加空间。 让间距:CGFloat = 8.0 button.contentEdgeInsets = UIEdgeInsets(顶部:0,左侧: 间距 ,底部:0,右侧: 间距 ) 当涉及titleEdgeInsets或imageEdgeInsets时,规则是向左右插图添加相等和相反的偏移量。 因此,例如,如果在左侧标题插图上添加8点,则需要在右侧插图上加上-8点。 这样,您仅使用插图来偏移标题或图像,而不以任何方式调整它们的大小。 如果不执行此操作,则计算的布局矩形可能会变得太小,标题可能会被截断,并且间距将显示一些奇怪的行为。 button.titleEdgeInsets = UIEdgeInsets(top:0,left:interval,bottom:0,right: 0 ) 要翻转带有图像的标题,我们可以使用imageEdgeInsets和titleEdgeInsets将imageView移动到titleLabel后面。 首先,我们将imageView的大小与按钮宽度向右移动,然后减去该图像的宽度,以使imageView保留在内容视图中。 它看起来像这样: 我们为右插图设置左插图的相反值: […]

iOS体系结构:MVVM-C,服务(6/6)

服务层是已经存在了数十年的设计模式。 它基于这样一个概念,即系统应分为不同的层(例如洋葱),每个层的每个层都有不同的职责。 服务层应该是与外界的连接,无论是数据库,远程服务器,蓝牙连接等。 在该服务层中,应该有多个服务,并且每个服务都应承担处理特定种类的服务或资源的单一责任。 基本上就是这样,它实际上是一个简单的概念,我们可能已经在我们的应用程序中以某种方式使用了它。 例如,我们通常有一个ApiClient类,该类处理服务器上的REST API。 但是我想指出的是,这与我们在整个系列中一直在构建的体系结构非常吻合的原因在于,我们应该组织和构造该层以充分利用它。 让我们继续研究ApiClient示例。 我们所有人都可能已经熟悉ApiClient的概念。 我们基于Apple的URLSession或其他框架构建一个负责发出HTTP请求的对象。 但这应该是它的唯一责任。 它应该不了解我们的模型和业务逻辑。 因此,如果所有这些业务逻辑都不能在ApiClient中,并且最肯定也不应在我们较低的ViewModel / View层中,应该去哪里? 这就是服务层的所在。 服务通常会包裹某种客户端(在本例中为ApiClient),并在其之上添加所有模型解析和业务逻辑。 我们可能很想创建一个ApiService来处理我们应用程序中的所有API需求,并且在一个非常简单的应用程序中它可能会起作用。 但是,我建议我们按逻辑单元来分隔服务(即使它们与本示例中的同类)相同。 例如,您可能具有一个用于处理登录/注册的SessionService和一个用于将图片张贴到服务器的PostService 。 这样,当向ViewModel注入服务时,它需要的是获取仅处理应用程序特定部分需求的特定服务 。 同样, SRP 。 这是一个非常简单的服务的缩写示例。 让我们在API上搜索位置的PlaceService 。 我们从一个概述操作的协议开始,我们将在此服务上调用该操作。 在这里拥有一个协议确实很有用,因为我们可能想要切换执行相同操作但使用不同来源(例如不同的API或缓存)的实现。 或者,与以往一样,它使测试变得更加容易。

学习Swift和iOS开发第2部分:Swift简介

在上一篇文章中,我们学习了如何安装Xcode。 在本文中,我们将使用Xcode深入介绍Swift的一些基础知识。 Swift是使用现代方法构建的通用编程语言,用于安全性,性能和软件设计模式。 如果您不具有计算机科学或编程背景,那么您可能会想:“那太好了。 但是这是什么意思? Trust”当我们说这意味着您的编码学习生活比以前容易得多时,请相信我们。 Swift是一种非常优秀的第一门编程语言,因为它的语法通常很容易理解。 在线上还有大量资源(例如教程(如本教程!),YouTube视频,博客,论坛等)可以帮助您学习Swift。 本章是后续各章的前提。 它主要供您参考和参考。 稍后我们将详细介绍。 让我们开始吧! 启动Xcode,我们将在一个称为Playground的地方工作。 只需打开Xcode并选择“游乐场入门”。 然后选择空白。 或从“文件”>“新建”>“游乐场” 命名并保存您的Playground,然后您应该会看到以下内容: 那么,这是什么游乐场? 游乐场是一个互动的工作环境。 我们可以编写代码,并立即查看我们的代码结果。 这使其成为学习和实验的好工具。 您可以在本文其余部分中看到的代码可以添加到您的Playground中以进行后续操作! 变数 每种编程语言都使用变量。 它们就像一个容器,可让您存储许多不同类型的数据。 要声明变量,必须使用关键字var : var讯息:String =“ Hello,World!” 我们刚刚写的内容告诉我们的计算机,我们想要创建一个容器(变量),其名称message为String类型,其中包含文本“ Hello,World!”。 Swift的惊人之处在于它包含了一个名为Type Inference的功能。 这意味着Swift可以分析变量内的数据(文本,数字,真/假等)并推断其类型。 要对此进行测试,只需在声明变量message之后删除String即可: var message =“你好,世界!” //类型推断的字符串 正如您在上面看到的,我们从未明确告诉我们的计算机我们希望variable为String但是由于Hello, World!周围的引号Hello, World! ,Swift可以推断出它的类型。 变量之所以称为变量,是因为它们是可变的,可以更改其值。 例如,如果我们想更改message变量的值,则需要编写变量名并按如下方式更改其值: var message =“你好,世界!” message =“你好,斯威夫特!” 现在message等于“你好,斯威夫特!”。 常数 有时,有些价值是您永远都不想改变的。 例如您的生日或您的家乡的名称。 […]

持续学习曲线(2018年3月)

3月1日,星期四 连接视图控制器 更好的初始化程序和默认参数:第二部分 3月2日,星期五 我如何在没有常春藤大学学位的情况下从微软,亚马逊和Twitter获取报价 通用表视图控制器— objc.io 3月5日,星期一 Swift中的代码封装 @objc和动态 何时以及如何在Swift中使用值和引用类型 用枚举堆叠视图 UIStackView 3月7日,星期三 添加POST请求— objc.io 问与答— objc.io SnapKit简介:简化iOS应用开发的自动布局 使用Swift包管理器对iOS项目进行依赖管理 3月8日,星期四 额外的IOS代码挑战,视频和讨论 Facebook的iOS 招聘过程中的期望 如何粉碎你的编码面试 如果您不害怕该怎么办? mikeash.com:就是这个家伙,你知道吗? 针对高级开发人员的iOS面试问题 3月9日星期五 为什么iOS开发人员不编写单元测试 Ledger Mac App:简介— objc.io 3月17日星期六 如何阅读成为更好的开发者的方式 设计iOS架构:动机 3月23日,星期五 如何在编程中不断学习 我一周内学习了所有数据结构。 这就是对我的大脑所做的。 下标 让我们使用UserDefaults简化工作 故事板值得一千个字 跟踪对讲中的事件 开发人员调查结果2018 模块化iOS第1部分:扼杀整体 3月24日星期六 基础架构即代码 揭秘核心位置权限 3月26日,星期一 飞行模式:离线启用Trello Mobile 同步变更 3月27日,星期二 […]

在Swift 4中解析JSON:基础知识

Swift标准库定义了一种用于数据编码和解码的标准化方法。 您通过在自定义类型上实现可Encodable和可Decodable协议来采用这种方法。 采用这些协议可以使Encoder和Decoder协议的实现获取您的数据,并在外部表示形式(例如JSON或属性列表)中对数据进行编码或解码。 为了同时支持编码和解码,请声明对Codable符合Codable ,后者将Encodable和Decodable协议结合在一起。 此过程称为使您的类型可编码 。 编码和解码自定义类型 如何在Swift 4中解析JSON? 让我们直接说清楚。 这是一个User的JSON示例: 为了将JSON转换为User实例,我们将struct标记为Codable 。 它应该看起来像这样: 然后,我们创建一个解码器: 还有BOOM! 这就对了!! 重要说明:我们使用了try! 并强行解包,但这只是出于示例的目的,您不应以这种方式使用它。 您应该使用catch来正确处理错误。 做一个好的开发者。 自定义键名 如果您的API采用蛇形惯例,则只需对CodingKeys枚举进行自定义实现。 该枚举定义了如何将属性连接到JSON字段名称。 因此,我们的User模型应如下所示: 来源和阅读链接 编码和解码自定义类型 将JSON与自定义类型一起使用

成为开发人员

没有计算机科学背景 品尝编程 我在高中期间学习了解决算法问题。 这是我第一次编程经验。 我对使用C ++感到非常兴奋。 它产生了有意义的结果。 我在高中部门的首尔信息奥林匹克竞赛中获得了大奖。 主修业务管理并作为数据分析师开始工作 我搬到美国学习业务管理,是因为我想学习更多有关管理组织以解决实际问题的知识。 这是我一生中非常愉快的经历。 有非常有组织的步骤来管理项目和人力资源。 大学毕业后,我开始担任商品数据分析师3年。 我已经使用Excel VBA和SQL进行报告。 这是处理大量市场研究和数据分析的一切。 我感觉就像是一家生产报告的工厂。 这就是为什么我开始iOS开发的原因 但是,除了通过创建报告来支持管理团队之外,我希望看到更现实的结果。 当时,我的妻子正努力使用iPhone Calendar App。 所以我想成为一个超级可爱的家伙,解决她的问题。 我开始研究iOS开发,终于在App Store上成功发布了我的第一个应用程序。 这是我的每日备忘录。 我的每日备忘录:在App Store上的内容 阅读评论,比较客户评分,查看屏幕截图,并详细了解“我的每日备忘录”。 下载“我的每日备忘录”并… itunes.apple.com 我的特长 英语是我的第二语言。 我在学习英语时学到的是,语言只是表达我的知识或思想的一种技能或方式,而不是目的。 (当然,有些人将语言用作翻译或翻译之类的目的。)编程语言是相同的。 它是我可以通过使用它表达我的想法的一种语言。 编程主要是关于如何为人们提供效率和便利,而不是技巧或技术本身。 如果说编程语言不是目的,那么我在大学学习业务管理的4年经验就是一种优势,而不是劣势。 您可以考虑一所法学院。 法学院的学生来自各个专业。 那里的主要目的是作为一名研究生从法学院毕业。 学过各种专业的人有可能通过进一步研究法律来改善社会对许多领域不了解行业的状况,从而丰富法律的解释,因此结果与实际不同。 我认为非计算机科学专业的人们将能够通过将他们的知识与编程相结合来找到市场想要的东西。 通过学习四年的业务,我了解了如何改变世界的见解,并且可以通过查看服务运营商和消费者的职位来进行编程。

依赖注入iOS让我们变得简单

依赖注入:拆分此英语术语以获取更简便的方法 依赖-您所依赖的东西 注入-用于注入东西 所以依赖注入意味着注入需要的依赖而不是创建它 或者我们也可以说将依赖注入到对象中,而不是负责创建对象依赖的任务 。 或某些怪胎将其定义为为对象提供实例变量,而不是在对象中创建实例变量。 😛 让我们以一个例子来获得更清晰的图像: 在这里的例子 关键是MyViewController负责创建Service实例。这意味着MyViewController类不仅了解Service类的行为。 它还知道其实例化。 现在在下一个DI示例中,我们在创建对象时将Service实例注入MyViewController实例。 尽管最终结果可能看起来与上面的示例相同,但事实并非如此。 通过从外部注入Service , MyViewController不知道如何实例化Service 。 简单来说,这就是依赖注入。 通常,依赖注入被认为是3种类型: 通过初始化程序进行依赖注入: 也称为基于构造函数,最优选的 是在初始化期间在构造函数 (构造函数) 中传递依赖项。在初始化程序中,通过将依赖项的属性声明为常量(使用let)来使基于DI的依赖项不可变。让它在整个客户的一生中都发生变化。 因为要求我们在初始化期间将服务作为参数传递,所以指定的初始化程序清楚地显示了DataManager类的依赖项。 通过属性进行依赖注入: 在类中声明的Internal或Public属性也可以用于将依赖项注入到类对象中。 这似乎很方便,但是它增加了一个漏洞,因为可以修改或替换依赖关系。 换句话说,依赖关系不是一成不变的。 使用serviceManager属性将服务依赖项传递给类MyViewController的viewController实例。 通过方法进行依赖注入: 依赖项也可以在需要时注入。 通过声明一个将依赖项作为参数接受的方法,这很容易做到。 在下面的示例中,该服务不是DataManager类的属性。 而是将服务作为方法的参数注入。 即使DataManager类失去了对依赖项,服务的控制,这种类型的依赖项注入也带来了灵活性。 为什么要使用依赖注射:- 测试:依赖注入使开发人员可以用模拟对象替换对象的依赖关系,从而使单元测试更易于设置和隔离行为。 透明度:通过注入对象的依赖关系,类或结构的职责和要求变得更加清晰和透明。 松耦合:协议和依赖注入的使用可以减少项目中的耦合。 协议在Swift中非常有用且用途广泛。 这是协议真正发挥作用的一种情况。 关注分离 :依赖注入严格地分离了对类的关注。如果类不负责实例化依赖实例,则它不需要知道如何做到这一点。 即使它与依赖关系的行为有关,但也不应与其实例化有关。 我们得出结论: 依赖注入是您在项目中可能已经在使用的东西,它的好处确实使结构易于理解,可重用,可测试和可维护,因此不要再键入几行代码,而是开始使用聪明的想法。 快乐编码 保持冷静和智能代码

迅速。 功能阵列

Swift为iOS开发带来了很多机会。 其中有一些非常有用的功能挂钩。 有些人立即将函数式编程与复杂的数学和M字相关联,但事实并非如此。 函数是函数编程中的真正力量。 在本文中,我们将介绍如何使用其中的一些功能,以使您的日常Array例程更加舒适,避免仅通过使用函数避免代码重复和不必要的键入。 回顾我的一位同事,我们讨论了下一个功能: 现在该回到我们的摘要了。 在第2行中,我们为将在第3行中使用的函数形成一个元组。因此,在第3行中,只要意识到offerCellReactorFactory参数是元组而不是,就可以使代码更甜美 self.offerCellReactorFactory($ 0.0,$ 0.1) 我们可以写 self.offerCellReactorFactory($ 0,$ 1) 那就对了! 元组的元素是函数的独立参数,因此闭包中不需要丑陋的点符号。 这是真正的魔术发生的地方。 类型推断是语言自动检测表达式类型的能力。 在声明变量时,我们每天都在使用它,但是它具有更强大,更漂亮的应用程序。 还记得我们的UIViewController.viewDidAppear声明吗? 该viewDidAppear变量存储一个函数,Swift能够理解该函数是什么。 很酷,但还有更多。 首先, Array的map函数采用一个非转义的闭包作为参数,因此不需要[unown self]。 现在,注意指针,第三行变成 .map(offerCellReactorFactory) 妈呀 在这里,类型推断为我们完成了所有工作。 Swift能够找出该特定表达式中的所有类型,因为我们的元组为该函数形成正确的参数,并且map本身采用了将元组转换为某种东西的函数。 我们只是节省了自己的打字时间。 此功能具有许多优点,从涉及重命名的较少键入和易于重构开始,到使用类型正确的表达式结束。 希望,这也阐明了为什么类型转换和强制转换很差的问题 。 谈论重命名…让我们将offerCellReactorFactory重命名为makeOfferCellReactor🙂 看看我们如何在第2行和第3行中应用两个映射函数。这种应用称为管道 。 实际上,可以将管道调用应用于某些值的一系列函数。 坦白说,我们的问题是功能的流水线应用。 但是此应用程序被变量声明破坏了。 这不好吗? 不,不是真的,但是Array不仅是像Int这样的普通类型。 数组是容器类型。 它通常封装许多元素,并且该数目在计算过程中可能会发生变化。 这被称为非确定性行为。 为了保留不确定性, 数组类型具有特定的属性。 他们为我们提供了我们刚刚描述的出色的管道应用程序功能。 您是否注意到地图返回了另一个Array ? 这样可以进一步应用诸如map , compactMap , […]