Tag: swift

使用CI / CD服务构建和部署项目

几个月前,我开始阅读有关CI / CD的文章,但是自上个月与朋友一起开始新的个人项目以来,我再也没有机会在项目中使用过它。 但是什么是CI / CD? CI或持续集成是一种将代码不断集成到您的应用程序中的能力,这意味着您每天/每周或您希望在任何其他时期将新功能和/或修补程序推送到您的仓库中。 持续集成(CI)是一种每天将所有开发人员工作副本合并到一条共享主线的实践(维基百科) CD或持续交付是一种能够安全,快速地连续发布软件的新版本的功能。 持续交付(CD)是一种软件工程方法,团队可以在短时间内生产软件,以确保可以随时可靠地发布软件(Wikipedia) 连续交付是一种以可持续的方式安全 快速 地将所有类型的变更(包括新功能,配置变更,错误修复和实验)投入生产或交付用户的能力 。 (continousdelivery.com) 为了实现这一目标,我们将使用像git(gitlab,github,bitbucket)这样的版本控制系统,开发人员可以将他们的工作推送到发布分支,他们的CI服务将提取该代码,构建,测试并将我们的应用程序部署到beta用户。 我们开始在Google上寻找CI,并发现了一些有趣的服务,例如Travis,Buddybuild,Bitrise,CircleCI和Jenkins。 Travis是免费的开放源代码项目,具有不错的UI,但这是一个私人项目,Travis没有免费的私人回购计划。 Buddybuild是我们的最爱,我们之前使用过它,并且在私人项目上免费使用。 不利的一面是为免费用户建立队列的等待时间很长,但是我们可以忍受。 我们没有尝试使用Bitrise,CircleCI或Jenkins。 对于这个项目,我们决定使用支持私有仓库和Buddybuild的Gitlab。 建立分支机构 我们有两个分支,将用于为我们的用户生成应用。 我们有一个开发人员分支将生成一个beta应用程序,一个主分支将生成一个AppStore应用程序。 您可以拥有多少个分支,例如,生产前分支或alpha测试员分支。 考虑到这一点,我们需要创建并保护这些分支,以便没人能向其中推送一些代码并最终破坏应用程序。 首先,我们需要创建一个新分支,您可以转到您的仓库并选择分支 ,然后选择新分支。 要保护分支,您需要选择设置进入存储库 向下滚动到“ 受保护的分支机构” 。 选择一个分支,然后选择将能够合并和推送的角色。 之后,您的分支将获得受保护的标签。 保护分支意味着没有人可以直接通过Pull Request(PR)或Merge Request(MR)将代码直接推送到该分支,这意味着在该项目上,一旦它被开发,我们将在另一个分支中开发新功能/修复。完成后,我们将其推送到Gitlab,他们创建了一个MR,以将该新功能/修复程序合并到开发人员中。 构建我们的应用 我们选择Buddybuild作为CI服务,因为它: 与Gitlab轻松集成。 私人回购是免费的,即使我们需要等待很长时间才能进行构建(有时等待时间约为一小时)。 在Buddybuild上创建帐户时,您可以选择将其与gitlab,github或bitbucket链接。 选择您的git服务,它将自动扫描应用程序。 它可以轻松,轻松地设置您的项目,完成后您将看到分支。 如果选择更多 -> 应用程序设置 ,则可以配置分支机构设置以及更多。 首先,我们要在不是开发人员或管理员的任何分支上禁用推送,因为我们将仅构建MR / PR,而不构建推送。 如果要构建推送,请启用此选项。 您可以在Buddybuild上设置很多配置。 如果您想了解更多信息,建议您阅读文档。 […]

在iOS中的UITableViewCell中自动扩展文本输入

在iOS中动态扩展视图从未如此简单。 正如我们在iOS的早期版本中所看到的,如果我们需要一个UILabel来根据其内容高度来计算高度,我们可以这样做,但是需要基于内容文本,字体,UILabel宽度等进行一些手动高度计算。它通过调用sizeToFit方法来增长。 对于文本输入,这从来都不是一件容易的事。 如果我们使用UITextField ,我们知道它最多只能输入一行。 对于多行输入,我们使用UITextView并使它可编辑。 但是问题是,我们必须设置它的高度或边界约束。 如果输入内容的高度超过了UITextView的高度,则它不会扩展,而是在该高度内内容可以滚动。 UITableViewCell的动态高度计算更加复杂。 但是在具有自动布局功能的iOS 8之后,生活变得更加轻松,因为苹果终于对它进行了外观设计。 好吧,这里的要求有些不同。 我们需要一个文本输入视图,该视图会随着内容高度的变化而自动增长/缩小。 这是操作方法。 首先,让我们创建一个Xcode项目并添加UITableViewCell的新子类。 说,我们的子类名称是QACell。 因此,让我们打开QACell.xib并根据您的要求添加TextView或UITextView的任何子类。 让我们在UITextView的顶部,底部,左侧,右侧添加边界约束,以便当UITableViewCell的高度发生变化时,其高度可以增加/缩小。 因此,添加约束后,它应该看起来像这样。 现在,打开UITextView的“属性”检查器,并禁用“滚动和弹跳”。 我们必须禁用滚动,因为启用滚动时,UITextView的框架与其内容大小无关。 但是当被禁用时,它们之间是有关系的。 我建议禁用跳动,因为我们需要在UITextView发生的每次更改时都更新UITableViewCell,当启用跳动并且TextView高度发生更改时,我们会有意外的跳动,这是我们所不希望的。 现在,让我们打开QACell.swift并为我们正在使用的UITextView添加一个IBOutLet。 然后是棘手的部分。 我们需要观察UITextView中内容的变化,这意味着当我们在UITextView实例中键入用户时,我们需要知道。 我们知道该怎么做,对吗? 我们需要实现UITextViewDelegate协议,并重写textViewDidChange(textView:UITextView)方法。 在这一阶段,我们知道用户何时通过委托在其中键入内容。 正如我们可以看到的变化一样,当发生变化时,我们必须通知UITableView更新当前UITableViewCell实例的高度。 但这不只是像往常一样重新加载单元格,因为如果我们重新加载单元格,则在键入每个字符之后,单元格将被重新加载,并且焦点将从当前UITextView实例中丢失。 因此,我们将无法正确键入。 而且,如此多次更新Cell绝对是一项昂贵的操作。 因此,让我们解决问题。 因为我们需要将输入更改的信息传递给我们的UITableView,所以我们将通过委托进行操作。 因此,让我们在其中编写一个协议和一个委托方法。 协议ExpandingCellDelegate { func updateCellHeight(indexPath:NSIndexPath,comment:String) } 现在,当UITextView实例的内容更改时,我们将调用委托方法。 因此,实现此协议的类(我们的ViewController)获得了更新特定UITableViewCell实例所需的消息。 在我们的代码中看起来像这样。 func textViewDidChange(textView:UITextView){ self.delegate.updateCellHeight(self.cellIndexPath,注释:textView.text) } 在这个阶段,我们已经完成了构建基础。 现在我们必须把这个事情付诸行动。 让我们打开具有UITableView的ViewController并实现UITableViewDataSource,UITableViewDelegate协议。 而且,实现我们之前创建的ExpandingCellDelegate 。 在cellForRowAtIndexPath中为QACell设置必要的数据源和属性,并像下面的代码一样设置委托。 cell.answerTextView.scrollEnabled […]

大中央车站0611

同步与异步: 同步函数仅在完成其订购的任务后才返回。 另一方面,异步函数立即返回,命令任务完成但不等待它。 因此,异步功能不会阻止当前执行线程继续进行下一个功能。 并发与发与并行 多核设备通过并行并行计算同时执行多个线程; 但是,为了使单核设备实现此目的,它们必须运行一个线程,执行上下文切换,然后运行另一个线程或进程。 这通常足够快地发生,从而给人以并行执行的错觉,如下图所示 串行队列: 串行队列中的任务一次执行一个,每个任务仅在前一个任务完成后才开始。 同样,您也不知道一个任务结束到下一个任务开始之间的时间。 这些任务的执行时间在GCD的控制下; 您唯一要知道的是,GCD一次只能执行一个任务,并且会按照添加到队列中的顺序执行任务。 并发队列: 确保并发队列中的任务以添加顺序开始。 项目可以按任何顺序完成,并且您不知道下一个任务开始所花费的时间,也不知道在任何给定时间正在运行的任务数。 这完全取决于GCD。 何时开始任务的决定完全取决于GCD。 如果一个任务的执行时间与另一个任务的执行时间重叠,则由GCD决定它是否应该在另一个内核上运行(如果有一个内核可用),或者执行上下文切换到另一个任务。 主队列,串行队列,一次执行一个任务。 但是,可以保证所有任务都将在主线程上执行,这是唯一允许更新UI的线程。 此队列是用于将消息发送到UIView对象或发布通知的队列。 串行执行的任务总是一次执行一次。 同时执行的任务可能会同时执行。 闭包是可以存储和传递的自包含,可调用的代码块。 调用它们时,它们的行为类似于函数,并且可以具有参数和返回值。 另外,闭包从其自己的作用域之外“捕获”它使用的变量-也就是说,它从封闭的作用域中看到变量并记住它们的值。

向Siri打个招呼

苹果宣布在上届WWDC中Siri将向开发人员开放。 因此,让我们在应用程序中使用它。 由于SiriKit是一个功能强大的框架,开发人员可以毫不费力地向其应用程序添加语音识别功能。 由于语音在Apple服务器中处理,因此Siri将需要Internet连接。 在将UITextView和UIButton放入视图控制器之前。 当用户点击按钮时,他/他将在UITextView上看到他/她在说什么。 您的应用需要获得许可才能捕获麦克风中的语音并加以识别。 因此,您需要在info.plist文件中添加两个字符串。 密钥为隐私-麦克风使用说明和隐私-语音识别使用说明 。 这些值是任意的。 当然,您将需要在项目中检查这些权限。 为了使用SiriKit,应导入Speech类。 您还需要使用SFSpeechRecognizerDelegate ,该方法只有一种实现方法, func speechRecognizer(_ speechRecognizer:SFSpeechRecognizer,availableDidChange可用:Bool) 。 代码 您可以使用上面的代码来测试设备中的语音识别。 别忘了模拟器不适合测试,因为您可以使用麦克风。 使用真实的设备进行测试。 如果您愿意,可以从下面的Github链接下载示例项目代码: onurtuna / SpeechRecognition-Swift SpeechRecognition-Example-Swift –用Swift编写的语音识别示例。 github.com

自定义CollectionViewCell

CollectionView或TableView的单元格通常都是一直被重复使用,但是重复使用只能使用一样的格式,如果说需要不一样的格式要如何实现? 在app中很常会看到这种分区块的画面,但如果画面内容太多,长度超过手机的画面时,用CollectionView是一个很方便的分块的方法,这个时候就需要自定义每一个cell的样式。 首先要让每个区块链的单元独立,所以每一个单元要各自有一个类,在Xcode中建立档案File-> New-> File-> CocoaTouchClass: 帮每一个区块链建立好之后,开始编辑每一个cell的内容,这边就不多重复述。编辑完之后如何把cell带进去CollectionView呢,如果有用过CollectionView应该会知道cell要先对CollectionView做注册,就算是在Storyboard上的cell也是要定义Identifier才能够让程式知道你是要使用哪一个cell。 接下来要决定在不同的情况呼叫不同的cell来用,在这边只是用很简单的判断式就可以做到: cell的变数要因为你的顺序而改变indexPath.row的值 还没有结束,如果只有这样子就会让你的单元格全部固定一个大小,而且不一定会是你需要的大小,所以我们要用FlowLayout中的方法来更改每个一个cell的大小: 这边要注意size的宽不能够超过CollectionView本身,不然CollectionViewLayout的宽设定出来会是错误的。 现在可以显示出你要的版本面,而且切好区块链之后能够针对一个区块链修改,以后如果需要增加区块链也不用全部重拉,只需要重新排个区块链的顺序,就可以修改画面。 希望这篇文章能够帮助大家更简单的编排UI,而且能更简单的修改。 Nibelheim11 / CustomCollectionViewCell 通过在GitHub上创建一个帐户来为CustomCollectionViewCell开发做出贡献。 github.com

比较NSCollectionView和UICollectionView#1

在将应用程序从iOS移植到macOS时,可以比较相似之处并移植代码。 自2015年使用OSX El Capitan 10.11(现称为macOS)以来,NSCollectionView已改进为现代API,看起来很像iOS的同级产品。 但是,仍有一些细微的更改,您需要进行研究才能注意到。 我将在以后的帖子中写这些。 这次,我将从内容容器的核心元素开始。 在macOS中,它称为NSCollectionViewItem。 在iOS中,您将找到它作为UICollectionViewCell。 内容容器的性质 为了指出这两个容器的基本原理,应从其祖先开始。 继承树如下所示: NSCollectionViewItem> NSViewController UICollectionViewCell> UICollectionReusableView> UIView 在macOS环境中,容器是一个控制器,它像其他View Controller一样具有一堆生命周期方法。 但是,在iOS中,它是一种视图,可以包含元素的子视图。 查看层次结构 为了继续上一点,默认情况下NSCollectionViewItem没有视图。 必须以编程方式或使用Interface Builder创建视图。 您可以在YouTube视频中了解有关如何构建此基础的更多信息。 在iOS中,它要简单得多。 假设您正在使用Interface Builder构建内容,只需将组件拖动到创建UICollectionViewCell附带的视图中即可 。 此外, UICollectionViewCell还具有一些访问视图的默认属性。 contentView-创建随附的默认视图 backgroundView —(可选)显示在单元格其他内容后面的视图 selectedBackgroundView —(可选)选择单元格时在背景视图上方显示的视图 在下一篇文章中,我将讨论准备此内容容器的区别。 参考文献 NSCollectionViewItem 项目是集合视图显示的最常见的元素类型,每个集合视图都必须位于… developer.apple.com UICollectionViewCell – UIKit | Apple开发人员文档 当一个数据项位于集合视图中时,UICollectionViewCell对象将显示该数据项的内容。developer.apple.com

Swift中的自定义运算符功能:矩阵加法

作为一名新程序员,我遇到了许多用于处理信息的新逻辑结构和工具。 但是,我每天至少使用一件事,这似乎需要零新学习:标准数学运算符+,-,*,/。 胜利! 加,减,乘,除…这些符号的工作方式与我在小学时进行简单算术问题时所用的方式相同。 好吧,不是那么快。 一会儿再思考:操作员到底是什么? 当操作数是相同类型时,运算符将在后台执行某些操作以返回结果。 为了简化和总结正在发生的事情,运算符是行为类似于函数但在语法上有所不同的构造。 确实,语法是我们在日常生活中遇到的语法,因此很容易忽略使这些运算符在编程上下文中工作的底层代码。 一旦将运算符视为函数,就自然会问:在另一个环境中,我如何能够实现这种类型的功能? 关于Swift编程语言的一件很酷的事情是,它很容易允许您为自定义和非数字操作数创建运算符函数。 由于我是一个数学迷,因此我选择矩阵作​​为探索如何编写自定义加法运算符的起点。 首先,我必须创建一个Matrix结构。 该结构具有三个存储的属性:矩阵中的行数,矩阵中的元素总数以及在给定这些参数的情况下生成的矩阵本身。 有两个计算的属性:矩阵中的列数和矩阵的字符串描述。 关于后者,我选择覆盖Matrix结构的默认print()输出,以呈现彼此堆叠而不是在超级数组中水平列出的行。 毕竟,这是我大学教科书中矩阵的外观! 刚刚了解了协议,这是我第一次使用该概念。 实现计算的描述属性是CustomStringConvertible协议的一项要求。 接下来,初始化器: 关于此初始值设定程序,最值得注意和有趣的事情可能是它返回了一个可选值。 必须且仅当元素可以在行之间平均分配以创建完美的“矩形”超数组时,才能确保初始化Matrix结构。 (向我的出色同学Cenker喊话,帮助我解决了嵌套循环!)现在,为Matrix结构体创建新版本“ +”的有趣部分是: 同样,与初始值设定项一样,“ +”函数返回可选的Matrix,因为仅当操作数矩阵具有相同维时才可以执行矩阵加法。 我在编写此函数时遇到了一些挑战。 首先,我最初解决该问题的方法是遍历Matrix结构本身。 我根据矩阵属性的[[Int]]类型错误地考虑了matrixA和matrixB。 但是,当我尝试编写对行和列进行迭代的嵌套for循环时,Xcode引发了错误: 我的错误很快变得很清楚。 for-in迭代功能不适用于我的自定义Matrix结构。 我做了一些阅读,发现Matrix必须符合SequenceType协议才能利用for-in循环。 我回头看了我的Matrix结构的内部工作原理,而不是实现该协议所需的功能,该功能将依赖于另一个符合不同生成器协议的自定义结构。 Matrix的哪些属性已经符合SequenceType? 为了实现我的目标,我该如何操纵这些属性而不是Matrix结构本身? 这就是我得出的对矩阵A和matrixB的元素[Int]属性进行迭代以计算总和的方法。 有用! 这是我做过的测试: 显然,要为矩阵数学创建一个全面的模型,还有许多工作要做。 最终,遵循SequenceType协议以利用直接迭代功能将是更理想的选择。 但是,瞧! 已经有开放源代码可以执行此操作: 矩阵结构参考 该集合还使用Apple的 mauriciosantos.github.io 提供了线性代数函数和运算符,例如inverse(),+和*。 尽管如此,解决这些问题有助于我更好地掌握操作员的能力和潜力,并加深了我对更高级的Swift编程约定(如结构和协议)的理解。

Cloud Foundry上的蒸气3

您对如何编写服务器端swift代码感兴趣,并且在第一个hello世界之后,您在脑海中听到了声音,例如“在哪里可以运行此代码”? 因此,一种解决方案是在swift运行时内的Cloud Foundry上运行它。 我知道服务器端快速是当前鲜为要求的话题,但是当我开始使用Vapor 3时,我意识到花了一些时间和一些研究才能在Cloud Foundry上运行它。 我的希望是,如果有人在那里尝试相同的内容,将会找到此博客文章,并且有助于使这些内容正常运行。 现在,让我们开始吧,让我解释一下如何将Vapor 3应用程序带到Cloud Foundry。 首先,您需要访问应在其上运行应用程序的Cloud Foundry环境。 接下来,您需要一个快速的应用程序,就我而言,它是一个简单的CRUD服务,可以处理待办事项。 作为标题 假设,此应用使用了蒸气3 Web框架。 我选择此Web框架,因为我将使用最新的Swift网络堆栈,更好地称为Swift NIO(2018年3月发布)。 Cloud Foundry(CF)的概念之一是对“ 12要素应用程序”模式的大力支持。 CF希望您遵循此模式,并按照“ 12因子应用”网页上主题3所述从环境变量读取所有配置。 在我的情况下,我必须提供一个数据库配置(PostgreSQL),并且对于cf运行时,我必须读取套接字配置,这两者都将通过环境变量提供。 服务器套接字的环境变量名称基于cf运行时。 为此,运行时使用标准变量VCAP_APP_HOST和PORT提供套接字配置。 为了简化本地开发设置,我采用了相同的方法并重用了它。 对于数据库,我使用自己的一组环境变量,并在所有变量前面都加上了PSQL *。 对于我的本地开发,我将所有内容都配置为本地资源,将套接字配置为127.0.0.1:8080,并将数据库配置为本地PostgreSQL数据库。 在CF运行时中,总是为我提供套接字配置,但是数据库变量必须由我自己提供,因此我必须将带有cf set-env的PostgreSQL变量添加到我的CF应用运行时中。 这样,我可以从cf环境中读取托管云PostgreSQL数据库实例的配置,就像在本地计算机上一样。 bash $ cf set-env snatch-todos PSQLHOSTNAME psql.clouddb.hostname.com bash $ cf set-env snatch-todos PSQLPORT 5432 bash $ cf set-env snatch-todos PSQLUSERNAME“ xxxxx” bash […]

iOS View Controller生命周期

介绍: 对于iOS应用开发,最重要的是了解应用生命周期并查看生命周期 通常,有三种方法可以在iOS中制作View Controller。 从.xib 从代码 通过情节提要 这是在生命周期视图中处于活动状态的所有方法: loadView 当视图控制器从代码创建时使用此方法。最好不要对由.xib或情节提要制成的此方法id视图控制器执行任何操作。 在视图加载中做什么:视图控制器在 请求 其 view属性但当前为 nil 时调用此方法 。 此方法加载或创建视图,并将其分配给 view 属性。在此方法中,viewController以编程方式创建。 viewDidLoad: 此方法在视图控制器生命周期中加载一次。在加载所有视图时调用此方法。在此方法中,它的优点是: 1.需要Onece的网络通话。 2.用户界面 3,其他需要一次完成的任务 注意:在此方法中,在定义边界和发生旋转之前为Call调用,因此在此方法中使用大小有风险。 viewWillAppear: 每次在视图可见之前和配置任何动画之前都会调用此方法。在此方法中,视图已绑定但尚未设置方向。您可以重写此方法以执行与显示视图相关的自定义任务,例如隐藏字段或在视图变为可见之前禁用操作。 viewWillLayoutSubviews: 默认情况下,它什么都不做。 当视图的边界改变时,该视图将调整其子视图的位置。 视图控制器可以重写此方法以在视图布置其子视图之前进行更改。 viewDidLayoutSubviews: 在更改其边界后,将viewController调整为其子视图之后,将调用此方法。如果要在设置子视图后对其进行更改,请在此处添加代码。 viewDidAppear: 在屏幕上显示视图之后调用此方法。 通常将数据保存到核心数据或开始动画或开始播放视频或声音,或开始从网络收集数据。这种任务类型适用于此方法。 viewWillDisappear: 从视图层次结构中删除视图之前调用的此方法。视图仍在视图层次结构上但尚未删除。 尚未配置任何卸载动画。 在此处添加代码以处理计时器,隐藏键盘,取消网络请求,将所有更改还原到父UI。 另外,这也是保存状态的理想位置。 viewDidDisappear: 从视图层次结构中删除VC的视图后,将调用此方法。 使用此方法停止侦听通知或设备传感器。 取消初始化: 在将视图控制器从内存中删除之前,它会被初始化。 通常,您可以重写deinit()来清除视图控制器已分配的资源,但这些资源不会被ARC释放。 请记住,仅因为不再可见VC,并不意味着它已被释放。 容器视图控制器(例如NavigationController)可以将其VC保留在内存中。 请记住,即使VC位于屏幕外,如果它仍在内存中,它仍然可以正常工作并可以接收通知。 didReceiveMemoryWarning() 当内存开始填满时,iOS不会自动将数据从内存移动到其有限的硬盘空间。 但是,它确实会发出此警告,并且您(我是说您)负责清除内存中的某些对象。 请注意,如果您的应用程序内存超过某个阈值,iOS将关闭您的应用程序。 […]

Swift的无服务器计算

为什么选择无服务器Swift? 与无服务器计算是否值得追求的问题不同,为什么要在Swift中实现无服务器系统? 有三个主要原因使Swift成为Lambda实现语言的理想选择。 首先,Swift是一种功能强大,健壮且富有表现力的语言,旨在在包括服务器端计算在内的各种环境中发挥作用。 就其本身而言,区别不大,因为可以用这种方式描述其他几种语言(Rust,Go)。 但是,Swift提供了两种附加的可能性-利用现有开发人员资源的机会,以及在系统的多个层(尤其是后端和移动客户端)之间共享代码的机会。 让我们考虑一个示例场景。 一个例子 我决定组建一家初创公司-这是我可以做的酵母菌,一家专门提供美味面包的在线面包店。 由于没有健壮的云基础架构,没有任何自重的面包店会被杀死,因此我的首要任务是构建微服务来处理向客户发送收据的工作。 具体来说,我想要一种服务,其输入是要订购的项目列表。 物品是面包的种类和数量。 例如三个羊角面包。 输入以JSON编码。 输出是收据的字符串表示形式。 它列出了每个订购的项目,其小计以及整个订单的总计。 现在,我不必担心收据太漂亮。 首先,我忽略了网络连接并编写了可用作命令行工具的代码。 首先,我将创建一个新目录,并使用Swift Package Manager(SPM)创建一个Swift应用程序。 请注意,该应用程序将命名为bru 。 姆迪尔布鲁 光盘布鲁 快速包初始化—type = executable 现在,我指定数据类型。 考虑到可重用性,我在与主应用程序不同的模块中定义它们。 我创建一个目录Sources / bruModels,并在该目录中使用以下代码创建Item.swift , Order.swift和Receipt.swift文件(完整列表可在https://gist.github.com/profburke/2e951f48542a9a1ff470515725727751c中找到): // Item.swift 枚举样式:字符串,可编码{ 羊角面包 凯恩 裸露镍 黑麦 } 结构项目:可编码{ 出租数量:整数 let style:样式 } // Order.swift struct顺序:可编码{ 公共私有(设置)各种商品:[商品] … } // […]