번第1部分,第2部分나누어서UI구축과表视图합니다。 하시면이틀을리클,하시면이지로연결다。 第1部分:UI UI发行版。 ( 변 :Xcode(iOS)용되는용되는code에서code code code code code code code code code code,,,,,,,,,,,,,, 보로보이는이도움이하며이하며알고알고알고알고알고용하시는。。드립니。。。。。。。。。。 构建基本的UI:기본UI구성하기 将UI连接到代码:코드와UI를연결하기 使用View Controller:View Controller와작업하기 实施自定义控件:커스텀실행하기 定义数据模型:数据模型정의기 와와에서는용하게와와와Xcode익숙해지는이는다。 Xcode的젝트의이며며이며,본젝트젝트어떻게하여야하여야하여야하여야를를를것입니다。 에서는FoodTracker간단한用户界面(UI)만들어보는로것으로하겠습니하겠습니다터하겠습니다。 될때면가을가때,될때면이름,음식이름을스텍리고이고정하기위한기위한이것입니다。 배우기 마치시면을정마치시면마치시면거에요거에요거에요거에요거에요거에요거에요거에요 Xcode프로젝트기 Xcode프로젝트이템플릿을구별하기。 。로젝트에서사이에서변환하기。 iOS시뮬레이터를실행하기。 UI토스토리보드추가하고,움직이고,사이즈를기。 属性检查器用户界面UI상에서기。 大纲视图를이용하여UI요소들을보요소들을,렬하정렬하기。 助理编辑의预览드이용하요스보UI UI를리보기。 用户界面自动布局。。를를를를를를를 새로운프로젝트생성하기 Xcode게임텝션션션,,,,,,본적인본적인본적인본적인본적인본적인본적인본적인。。。。。 。다수의이템플릿이스인터페스소스코드리구성하고다。 (정과가장기본이템플릿을다(Single View Application_View가하나인)。 새로운프로젝트생성하기 Xcode를。 Xcode실행이처음이신경우,용자다추겁니다겁니겁니다 Xcode설정이실행이준비가크린샷을있도록통한시통한따라주시바랍니바랍니바랍니바랍니다바랍니다。 欢迎来到Xcode것입니다。 마세요이아닌이젝트로젝트이나타나더라도정마세요,전에이전에이미로젝트겁니다。 。로젝트다음아이템을이용하시면다。 2.欢迎화면에서,创建一个新的Xcode项目또는(文件선택>新建>项目)를。 고로운이열리고,선택할이보일거에요。 […]
我喜欢服务器端开发,也喜欢Swift,因此很显然我对服务器端Swift感兴趣。 但是如果没有Docker,现代的后端开发是不可能的(至少是极其混乱的)。 幸运的是,我们能够在Docker容器中运行Swift应用程序。 Swift的常规Dockerfile通常看起来像: 来自swift:latest 添加。 / app WORKDIR / app 运行快速包解析 RUN快速构建-配置发布EXPOSE 8080 ENTRYPOINT .build / release / SwiftDocker 这是简单明了的示例。 但不幸的是,结果容器将很大,约为1.35G。 这使得处理图像变得困难。 至少我的Mac上只有250G,因此我必须处理此问题。 Docker支持多阶段映像。 当您在一个图像中构建某些内容并将其复制到另一个图像中时。 它提供了在完整映像中构建应用程序的可能性,但仅使用最小映像即可运行它:OS +必要的库。 我总是在Golang应用程序中使用这种技术。 Go编译器能够创建一个包含所有依赖项的可执行文件。 不幸的是,Swift编译器在静态链接标准库和Foundation时存在一些问题。 我在本文“最小化Swift Docker映像”中找到了可能的解决方案。 但是直接从文章解决方案对我没有用。 所以我修改了它。 主要思想是使用ldd确定哪些共享库需要二进制文件并将其压缩到存档中。 #!/ bin / bash BIN =“ $ 1” OUTPUT_TAR =“ $ {2:-swift_libs.tar.gz}” TAR_FLAGS =“ hczvf” DEPS = $(ldd $ […]
一,为什么要使用UI测试? 1.自动化手动测试🤖 测试应用程序时,我们总是重复相同的过程以测试我们没有破坏任何东西。 我们可以通过一系列与手动测试相同的测试来实现这一目标。 2.表示层中的逻辑丰富🌅 我们拥有的UI逻辑越多,我们测试的内容就越多 3.节省时间⌚️ 有了一系列的ui测试,我们可以在更少的时间内每次都重复相同的手动测试。 二。 我们可以测试什么? 纽扣 刷新表格 输入文字 滑杆 检查导航栏标题 推拉视图控制器 重新排列细胞 等等.. 您可以查看此UI测试备忘单以获取更多信息。 三, 我们如何正确测试? 1.有助于将逻辑与表示法separate分开的架构。 当我们谈论MVC时,我们都知道它不是非常可测试的,因为视图和控制器之间的交互非常紧密。 我们可以使用MVVM或VIPER架构,通过更好的分布来实现更好的可测试性。 您可以查看这篇很棒的文章,以获得更多信息iOS体系结构模式。 2.依赖注入💉 这种软件设计模式允许在运行时而不是在编译时选择组件,目的是用Test Doubles代替生产代码。 依赖注入的示例将类似于以下ServiceLocator: CharactersViewController :是主视图控制器,并显示GOT字符列表。 CharacterDetailVC :显示CharacterDetailVC的详细信息。 字符VC测试 辅助方法 我们将在测试中使用一些辅助方法。 我们将不再需要手动重复此过程this。 五,从这里去哪里 在github上检查整个项目,查看所有使用的配置和框架。 尝试自己编写一些UI测试。 创建您自己的项目,并按照此结构做一些事情! VI。 归因 GOT Challenge Swift应用程序基于Idealista GOT Challenge Android。
您好,我亲爱的开发人员, 本文是我最近谈论的主题的延续: 无人问津的常见错误– Swift Bools 您好,我亲爱的开发人员,有时您可以编写一个在语法级别上没有重复的代码… blog.idapgroup.com 最近,我偶然发现了〜sh…〜代码中的一块宝石。 让我向您介绍所有辉煌的代码。 您已经在许多不同的面孔上看到了它,但是它总是归结为以下内容: 现在还为时过早,即使您没有编写这样的代码,也要拭目以待。 您不应该考虑类型和方法,而只考虑代码的思想。 这个想法很简单。 您可以将相同的值设置为具有相同接口的不同对象的多个属性或方法。 首先,代码是计数器DRY,它只是不使用Bool作为Bool 。 这里也有很多重复项。 因此,更好的方法是重构如下代码: 对? 对? 错误! 对于相同的变量,我们已经对isUserInteractionEnabled进行了重复数据删除调用,但是仍然有2个调用isUserInteractionEnabled和2个调用isOn 。 在一个函数的范围内多次调用任何属性本身就是一个缺陷。 即使您的属性在访问期间以最小的开销存储,它也可能在多线程环境中发生变化,或者通过一些复杂的观察代码变得可观察,甚至通过一些困难的计算也可以观察到。 因此,最好的准则是通过正确地分解代码并缓存方法/属性结果,永远不要在函数中多次访问属性或调用方法: 这样做要好得多,但是可以想象,在某个时间点, isUserInteractionEnabled将重命名为userInteractionEnabled 。 搜索代码以查找用法将很麻烦。 让我们尝试避免多次调用isUserInteractionEnabled来实现更好的重复数据删除: 哇 该代码很短。 但这好吗? 在视觉层面上,没有重复。 但是,复制仍然存在。 这是逻辑上的重复,因为我们对每个方法都调用isOn (对于该特定情况为两次)。 所以,让我们缓存它,对吧? 那好多了。 现在,让我们听取我的建议,并考虑将来的用法。 我对YAGNI(您不需要它)原则没有任何意见,我只建议考虑分解,因为小的可链接函数是编写,更改和重用想法的更好方法。 假设我们必须添加另一个要禁用的视图。 假设我们不仅要启用或禁用按钮,还要将其背景色更改为相同的颜色。 假设我们希望能够在完全不同的不相关代码段中启用/禁用视图。 该解决方案的核心是简单且可重用: 让我们分析一下: 我们创建类型别名以使代码更具可读性,并避免编写困难的语法构造。 是的,我认为在代码的多个位置用大括号编写UIView很困难,因为这需要额外的击键,并且自动完成功能无法为您提供帮助; 我们创建视图数组的访问器,如果要更改要处理的视图,则只需在一个访问点中执行此操作,就可以避免重复。 我们创建了enable,可以在代码的不同位置使用它,而无需重写相同的方法或使用继承。 如果属性是一阶函数(它们位于编译器的内部,只需检查AST,但是Swift不会让我们那样使用它们),则可以进一步改进。 我们当然可以通过传递闭包来模拟这种行为: 那只是口味的问题,是一项特殊的任务。 我并不总是使用这种方法,但是我也不能总是避免使用它。 […]
您好,我亲爱的开发人员, 今天,我要说的是那件事,这让我很困扰。 您知道,我是一家软件开发公司的CTO。 此外,我是许多其他软件开发公司和初创公司的朋友,我帮助他们建立了移动编码文化或只是采访了人们。 因此,我在审查他人的代码方面拥有丰富的经验。 我这样做是在面试,性能审查,代码审查中赚钱和/或赚钱。 你知道吗? 由于人们容易犯的简单错误,我感到很沮丧。 因此,在本系列文章中,我将向您展示改善代码并使代码更具扩展性和可读性的不同方法。 是的,我会不时抱怨和抱怨。 首先,我将给出一般建议: 干(不要重复自己); 了解您正在使用的乐器; 反思您的代码; 扩展您的视野以改善代码。 第二个建议实际上是第一个建议的专业化。 您会发现,如果您不知道所使用的语言或框架,您将复制该代码。 我可以承认,我每年至少要对代码进行4次反思,每发现一次,平均每分钟就会产生100 WTF。 然后,我将自己的命运视为无能的傻瓜。 然后,我寻求更好的解决方案,然后尝试避免此类错误。 通过扩大视野,我的意思是学习新的语言和范例。 最近,我开始学习FP,可以告诉您,我永远都不会像以前那样编码。 当我仍然在ObjC中编写Ruby时,也发生了同样的情况。 总体而言,您尝试的次数越多,您的代码就越好。 正如Paul Graham曾经说过的那样,您将永远无法用其他语言编写类似Lisp的代码,但是即使您知道Lisp,即使使用更有限的语言,您的代码也肯定会变得更好。 第一个建议是国王,因为重复会导致不良的可重用性和可扩展性,从而导致大量容易出错的代码,这会消耗程序员的时间,例如胖而毛茸茸的野生不死人类不育之猪,充满了愤怒。活的。 修改这样的代码真的很难。 让我们看一下下面的代码: 这里的代码非常简单,但是如果要为前缀函数将“ prefix”字符串更改为“ mama” ,而对于后缀函数则保持不变,则更改代码会很麻烦。 这里的解决方案非常简单。 切勿使用代码中硬编码的任何类型的常数(字符串,数字,对象或其他任何形式)。 将它们放在带有清晰名称的词法范围常量中。 可以使用以下建议将上面的代码重写如下: 与特定内容相关的任何更改都在一个地方完成,这是重复数据删除和DRY的最终目标。 就是这样,伙计们。 祝您有美好的一天,无论您身在何处,都要保持干燥。
如果您刚刚开始学习编码之旅,那么您可能听说过面向对象编程。 它是一种广受认可的编程模型,它经受了时间的考验。 它开始达到可以被其他更现代的模型(如Protocol-Oriented Programming所取代的地步,但是理解它仍然非常重要。 类是OOP(面向对象编程)的关键组成部分,它使我们能够创建排序的蓝图,然后根据需要对其进行复制和修改。 一个例子可以是汽车工厂中的汽车。 想象一下,工程师为汽车创建了一个蓝图。 在工厂中,您可以按照蓝图中列出的计划,使用该蓝图创建同一辆汽车的多个副本。 让我们创建我们的头等舱,并使用上面的car示例。 配置 首先,如果尚未打开Xcode,请点击Create New Playground 。 给它起一个类似“班级”的名称,然后单击“ Next 。 选择某个位置以保存此.playground文件,然后单击“ Create以保存它。 您应该会看到类似下面的屏幕。 删除左侧的所有样板代码,但根据需要保留import UIKit 。 创建您的第一堂课 在您的Playground窗口中,输入以下内容来创建一个类: 车辆类别{ } 我们使用了关键字class后面加上了Vehicle类的名称。 最好的做法是,以大写字母(即“车辆”,“摩托车”,“踏板车”)开头课程名称。 添加变量和函数 现在,我们需要为我们希望所有汽车拥有的属性添加变量。 像这样: 车辆类别{ var轮胎= 4 var大灯= 2 var马力= 468 var model =“” func drive(){ //加速车辆 } func刹车(){ //停止车辆 } } 如您所见,类可以具有描述它的属性(例如, tires , headlights , […]
DispatchSource使调试变得容易,在运行时分析视图更改,对象状态更改。 在这里,我将描述一种随时随地(运行时)更改对象状态的方法。 我们可以使用断点从调试器更改对象状态。 但是,断点仅在应用于要执行的代码时才能停止执行。 但是,如果我们必须随时随地进行此操作,那么我们就不能依赖于自定义代码的断点。 解决此问题的方法之一就是使用DispatchSourceSignal 我们大多数人都知道DispatchQueue,Qos类,使用DispatchGroup等。 但是我们并不十分了解DispatchSource提供的api和功能。 从Apple Doc: DispatchSource提供了一个接口,用于监视低级系统对象(例如Mach端口,Unix描述符,Unix信号和VFS节点)的活动,并在发生此类活动时提交事件处理程序以分派队列以进行异步处理。 因此,让我们看一下这种信号监视如何使我们能够随时随地更改对象状态,这在调试过程中会非常方便。 该信号应在应用程序的调试模式下使用,以阻止您的应用程序在生产环境中的洞察力,并保护您的应用程序免受攻击者的侵害。 该代码将很快,所以我假设所有人都知道迅速的基本语法,尽管ObjectiveC中也提供了相同的api,所以让我知道是否需要知道。 让我们添加一个全局属性声明以在传递的对象上启动信令。 对于我的用例。 我在类声明上方添加此属性。 通过viewDidLoad设置信号,如下所示: _ = setupSignalHandlerFor(自己) 方法说明逐步 如前所述,我们将仅在调试模式下进行此设置。 我们声明一个可选的源信号参数。 启动信号以监视主队列上的SIGSTOP Unix信号。 当收到信号时会添加事件处理程序。 源以挂起状态开始,因此可以通过调用resume来启动 现在,我们为Unix Signal设置了信令,可以用来更改对象状态,正确.. 您是否在问同样的问题,如何用于更新对象状态? 让我们解开谜团 现在,以调试模式运行您的应用,并设置信号发送。 使用此处提供的控件暂停应用,然后再次播放。 再次播放它将击中您的信号,并且您的日志语句将被打印。 现在,如果将断点放在打印语句上,则可以通过暂停和播放来拦截应用程序中任何位置的执行。 现在看看我如何用它来更改对象状态。 在调试器中编写: 宝物 将打印“ ”” 因此,这意味着对象是我们的控制器实例,并且其属性可以更改。 例如,切换按钮的隐藏状态。 expr object.searchButton.isHidden = false Xcode调试器有时可能无法直接对对象实例进行更改。 在这种情况下,我们必须声明一个指向对象的调试变量,如下所示: expr let $ vc = unsafeBitCast(0x7fb43d40fbf0,to:YourModule.ControllerName.self) […]
Zip()可以节省您的时间,只需在代码中为其留出空间即可。 创建由两个基础序列构成的对对序列。 您可能不理解这些词的意思,那是我第一次读到的词,但是通过练习和一些搜索,可以用简单的词来定义它并显示它的作用。 zip(_:_:)函数旨在将两个序列合并为一个元组序列 有例子可以使事情变得容易: 让 sequence1 = [“” ali“,” ahmed“,”穆罕默德“] 让 sequence2 = [1,2,3] 让 mergedSequence_zip = zip(sequence1,sequence2) 打印(数组(mergedSequence_zip)) // [(“ ali”,1),(“ ahmed”,2),(“ mohamed”,3)] 看这个简单的例子知道会发生什么。 zip()将sequence1的第一项与sequence2的第一项合并/合并,并将这两项作为元组,对于第一项,然后对第二项和第三项进行相同的步骤 有zip的注释,zip()是否仅适用于Array? –没有 Zip()允许您使用Arrays,Sets,Dictionary或任何符合sequenceType协议的类型 因此,我们来看zip()对Dictionary类型的作用示例: let sequenceDic1 = [“名称”:“ ahmed”,“地址”:“伦敦”] let sequenceDic2 = [“名称”:“穆罕默德”,“地址”:“法国”] 让 zipDics = zip(sequenceDic1,sequenceDic2) 打印(数组(zipDics)) // [(((key:“ name”,value:“ ahmed”),(key:“ name”,value:“ Mohamed”)),(((key:“ address”,value:“ London”),(key:“地址”,值:“法国”))] 这次发生了什么,这是元组类型的数组,为简单起见,让我们访问第一个元素。 打印(Array(zipDics).first!) […]
持续集成的过程执行各种活动,例如分析,构建,测试和部署iOS应用。 将每个构建任务分解成各个阶段并独立执行它们是一个好主意。 此过程也称为构建管道或部署管道。 作为iOS开发人员,您可能已经体验到构建iOS应用可能需要很多时间才能进行测试。 管道是处理iOS开发的各个阶段以获得快速反馈的方式。 在花费了数小时的构建和测试阶段之后,我们可能不想因代码样式问题而导致构建失败。 自托管的持续集成服务器(如Jenkins和TeamCity)具有创建构建管道的良好支持,但是基于云的CI服务器(如TravisCI,CircleCI等)也正在推出部署流水线功能。 在这篇文章中,我们将看到如何使用Travis Stages功能设置iOS部署管道。 请注意,我以TravisCI为例,因为我将其用于一些开源项目。 其他可能基于CI的CI服务器也可能具有类似的功能。 iOS部署阶段 在进入TravisCI设置之前,我们将了解部署任何iOS应用的重要阶段是什么。 主要的构建阶段是 分析源代码中的代码样式问题 使用XCTest或其他框架进行测试 构建和存档iOS应用 将iOS应用分发到其他Beta测试服务 将iOS应用上传到iTunes Connect 这些是必须在连续集成服务器上自动化的主要阶段,才能实现自动部署。 特拉维斯舞台 万一TravisCI刚开始使用,它是一个嵌入Github的基于云的持续集成平台,该平台允许为开源以及企业项目运行CI构建。 它具有良好的文档,可帮助您开始进行持续集成。 TravisCI宣布了Travis Stages的新功能,以实现针对开源项目和企业项目的部署管道。 可以通过在.travis.yml文件中添加以下代码示例来启用这些阶段 工作: 包括: -阶段:测试 脚本:./ test 1 -#阶段名称不是必需的,将继续使用`test` 脚本:./ test 2 -阶段:部署 脚本:./ deploy 为了在iOS项目中应用此原理,让我们在GitHub上创建一个开源项目,如下所示(您可以使用任何iOS应用) 在Xcode中创建名为SwiftLint-CI的空白单视图应用, 其中包含单元和UI测试目标 使用CocoaPods添加SwiftLint来检查Swift代码语法。 这可以通过创建Podfile并运行pod install命令来完成。 现在,我们已经为CI配置了一个基本的iOS项目。 现在,我们可以添加支持以在TravisCI上运行构建并启用以下阶段。 使用SwiftLint为Lint Swift代码构建阶段 构建阶段以运行单元测试 构建阶段以运行UI测试 使用阶段创建.travis.yml TravisCI使用macOS虚拟映像来运行构建,所有映像的列表都可以在此处找到。 我们可以选择最新的xcode9图像来运行演示应用程序的构建。 […]
您好,我亲爱的开发人员, 苹果在Swift中引入了一个非常可怕的东西,它破坏了所有的安全性和完整性检查,并且消除了使用Optional作为安全类型的麻烦。 这件事是力量的阴暗面。 是操作员! 。 关于使用它,我有一些建议: 不要用作! ; 不要使用变量!.doSomething() ; 不要使用let变量:输入! 。 切勿使用强制操作员; 永远不要使用强制操作员; 你不是绝地,不要使用武力; 你也不是西斯,不要用武力; 不,就是不; 杀死所有使用它们的人,烧掉他们的房屋并吃掉它们的小猫; 更重要的是,您永远都不敢自己使用它们。 强制运算符的最大问题在于,Swift并不是鸭子类型的ObjC,如果它们具有相同的接口,则可以避免使用一个对象,而使用另一个对象。 它也不是安全的,就像ObjC一样。 您不能在Swift中将消息发送到nil,而在ObjC中将消息发送到nil则返回nil(即使在ObjC中返回结构的消息仍然不安全)。 这意味着,如果您使用强制,将永远无法确定自己的Swift代码。 您也将无法对此进行推理。 即使,如果您确定,使用force操作符的代码也将按预期运行,则有可能在前一天发生更改,因为您忘记并且无法提供适当类型或适当值的变量。 使用武力的主要原因是开发人员太懒了,无法编写适当的结构良好的可预测代码。 克服懒惰,不要使用强制运算符。 因此,请记住,每次在Swift中使用武力时,您都别无选择。 他必须至少杀死一只小狗和一只小猫。 所以,对动物好,不要用力。 最后,让我再次强调: 请勿使用强迫操作员 没有例外 就是这样,伙计们。 祝您有美好的一天,无论您身在何处,都要保持干燥。