Tag: 开发

从底部到UITableView布局的有趣解决方案

这里,我们设计了一个表格视图,该表格视图从下至上添加了单元格。 在研究StackOverflow https://stackoverflow.com/questions/28105905/how-to-populate-uitableview-from-the-bottom-upwards之后 我发现主要有两种解决方案: 1- 翻转UITableView翻转单元格 ,然后反转UITableView中每个单元格的顺序。 问题: ScrollViewIndicator向左旋转。 滑动删除操作将引起混乱。 2 —计算所有单元格,部分标题和部分页脚的总高度 ,然后设置UIEdgeInsetTop 将其向下推 。 问题: 该解决方案很复杂,很难与Autolayout / UITableViewAutomaticDimension一起使用。 我提出了解决这些问题的解决方案: 如您所知,使用自动布局设置多个UILabel可以根据字体大小,字符数等自动调整内容大小。 相同的解决方案可以应用于这种情况: 首先,使用它来根据内容大小计算内部布局: 类IntrinsicTableView:UITableView { 覆盖var contentSize:CGSize { didSet { self.invalidateIntrinsicContentSize() } } 覆盖var internalContentSize:CGSize { self.layoutIfNeeded() 返回CGSize(width:UIViewNoIntrinsicMetric,height:contentSize.height) } } 设置UITableView左右左右的布局 设置顶部布局> = 0,以便视图可以从顶部浮动到底部而不会溢出父视图 tableView.snp.makeConstraints {(m)在 m.left.bottom.right.equalToSuperview() m.top.greaterThanOrEqualToSuperview() } 结果: 底部的UITableView布局。 通过设置基本TableView或仅处理几行代码,即可轻松应用于任何地方。 使用此解决方案,无需计算页眉,页脚,单元格的高度,并且同时使TableViewCell上的Swipe正常运行。

Swift中网络单元测试的完整指南

面对现实吧,编写测试在iOS开发中并不那么流行(至少与为后端编写测试相比)。 我曾经是一个单独的开发人员,但最初并未受过本地“测试驱动”开发人员的培训。 因此,我花了很多时间研究如何编写测试以及如何编写可测试的代码。 这就是为什么我要写这篇文章。 我想分享我在Swift中进行测试时发现的东西。 希望我的见解可以节省您在丛林中奔波的时间。 在本文中,我们将讨论测试101的开始: 依赖注入 。 想象一下,您正在编写测试。 如果您的测试目标(SUT,被测系统)以某种方式与现实世界相关,例如网络和CoreData,则编写测试代码会更加复杂。 基本上,我们不希望我们的测试代码依赖于现实世界中的事物。 SUT不应依赖于其他复杂系统,因此我们能够更快,时间不变和环境不变地对其进行测试。 此外,重要的是我们的测试代码不要“污染”生产环境。 “污染”是什么意思? 这意味着我们的测试代码将一些测试内容写入数据库,将一些测试数据提交至生产服务器,等等。这就是存在依赖项注入的原因。 让我们从一个例子开始。 给定一个应该在生产环境中通过Internet执行的类。 Internet部分称为该类的依赖项。 如上所述,当我们运行测试时,该类的Internet部分必须能够用模拟或伪造环境代替。 换句话说,该类的依赖关系必须是“可注入的”。 依赖注入使我们的系统更加灵活。 我们可以在生产代码中“注入”真实的网络环境。 同时,我们还可以“注入”模拟网络环境来运行测试代码,而无需访问互联网。 TL; DR 在本文中,我们将讨论: 如何使用依赖注入技术设计对象 如何在Swift中使用Protocol设计模拟对象 如何测试对象使用的数据以及如何测试对象的行为 依赖注入(DI) 开始吧! 现在,我们将实现一个名为HttpClient的类。 HttpClient应该满足以下要求: HttpClient应该使用与分配的URL相同的URL提交请求。 HttpClient应该提交请求。 因此,这是我们的HttpClient的第一个实现: 似乎HttpClient可以提交“ GET”请求,并通过闭包“ callback”传递返回的值。 HttpClient的用法 问题是:我们如何测试它? 我们如何确保代码满足上面列出的要求? 直观地,我们可以执行代码,为HttpClient分配一个URL,然后在控制台中观察结果。 但是,这样做意味着我们每次实现HttpClient时都必须连接到Internet。 如果测试URL在生产服务器上,那似乎更糟:您的测试运行在一定程度上确实影响了性能,并且您的测试数据已提交到真实世界。 如前所述,我们必须使HttpClient“可测试”。 让我们看一下URLSession。 URLSession是HttpClient的一种“环境”,它是Internet的网关。 还记得我们所说的“可测试”代码吗? 我们必须使Internet组件可更换。 因此,我们编辑HttpClient: 我们更换 与 然后我们添加一个新变量: […]

使用DBDebugToolkit调试iOS应用

“从CI获得的构建数量让我们有点不知所措。 我们安装了很多版本,过了一会儿我们不太确定我们当前在设备上安装了哪个版本。 您可以在应用程序中的某个位置添加版本并生成编号吗?” 我将永远记得在nomtek的那一刻,我们的一名测试员告诉我这个问题。 那是一个大项目的开始,所以我知道迅速解决它会在将来对他们有很大帮助。 当然,这没什么大不了的,有很多方法可以实现:咨询设计师后,可以将其添加到一个屏幕中,将其添加到“设置捆绑包”甚至是应用程序图标中。 暂时,我们将其添加到了应用主屏幕上的标签之一。 但是,在此之前,我问了一个使一切与众不同的问题:“ Android团队的朋友如何解决这个问题?”。 事实证明,他们使用的库使他们可以轻松访问许多调试工具。 您只需在屏幕上向左滑动即可显示菜单。 我真的很喜欢这个主意。 我立即开始搜索现有的库,这将有助于在iOS上实现类似的功能。 令我惊讶的是,我找不到任何类似的东西。 我一直对开放源码着迷。 当时我正在等待一个值得花些空闲时间来思考的想法,所以我很兴奋并且有动力开始在自己的图书馆工作。 当我回到家时,我打开了一个空文档,并开始写下我想在那里看到的所有功能。 在许多漫长的夜晚之后,我发布了DBDebugToolkit的第一个版本。 我的目标是提供尽可能多的有用功能,同时保持安装过程的顺利。 本文将研究DBDebugToolkit可以帮助您解决的iOS开发中常见的三个常见问题。 使用服务器 如今,绝大多数应用程序都依赖于服务器提供的数据。 通常情况下,核心业务逻辑是远程执行的,但有时在测试中可以忽略它,部分原因是后端API调用的异步特性。 此外,如果服务器端与您的应用程序同时开发,则应为一些初始问题做好准备。 DBDebugToolkit提供了您的应用程序执行的所有HTTP请求的列表,甚至包括尚未收到响应的HTTP请求。 如果响应中包含图像,则可以看到持续时间,HTTP代码甚至是缩略图。 还可以过滤列表以仅包含URL中具有指定子字符串的请求。 每个请求都可以进行彻底检查。 您可以看到所有HTTP标头和主体详细信息。 正文详细信息屏幕支持文本和图像。 如果请求以错误结尾,您还将看到所有详细信息。 作为经常使用DBDebugToolkit的人,我认为请求列表是最有用的功能之一。 它使我更仔细地了解了应用程序中至关重要但又隐藏的部分,节省了检查后端API文档所需的时间,甚至还帮助发现了琐碎的问题,例如两次发送请求。 有很多工具可以向您显示应用程序发送的请求,例如Charles Proxy。 使用DBDebugToolkit进行网络调试的独特之处在于始终启用它。 当您最终重现您担心的错误并意识到即使没有连接调试器或未启用代理时,也已经为您记录了所有请求,您一定会感激不尽。 此外,一旦从服务器获取数据,DBDebugToolkit可以帮助您验证数据到底发生了什么。 它允许您浏览文件,钥匙串, UserDefaults ,Cookie甚至是Core Data。 验证布局 我将永远记住的与DBDebugToolkit有关的另一种情况是我们的设计师Michał问我是否可以帮助他使用我的库时。 设计评审通常是开发过程的一部分,尤其是在您追求像素完美的时候。 但是,在iOS上进行操作比在Android上麻烦得多,在Android上,您可以使用单独的应用在应用顶部绘制网格并查看是否正确对齐。 iOS上的沙箱无法实现。 相反,可以使用DBDebugToolkit将负责绘制网格的代码注入到您的应用程序中。 我必须承认,我感到as愧的是,起初我只是在考虑开发人员和测试人员,而没有意识到iOS环境对设计师也很苛刻。 感谢Michał在(沙)盒子外面思考! DBDebugToolkit允许您在应用程序顶部绘制高度可定制的网格覆盖。 您可以指定覆盖图的大小,不透明度和颜色,以适合应用程序的边距和配色方案。 网格覆盖将在应用程序的开发和设计审查期间为您提供很多帮助。 它背后的故事是我最喜欢的开源方面之一的完美示例-它根据用户的需求而发展。 除了网格覆盖之外,DBDebugToolkit中还包含一项附加功能,在设计审查期间可能会有所帮助。 […]

固体-iOSразработке。 Принципединственнойответственности

Введение ВэтомциклестателбырассказатьоSOLIDпринципах,и,чтосамоеглавное,дополнитихпра Понимаясмыслиспользованиякаждогопринципа,从 Немногоистории Вначале2000-хРобертМартин,такжеизвестныйкакдядюшкаБоб,придумалсписокиз11принриоооое Первые5принциповописывали,каксделатьхорошийдизайнкласса。 使用SOLID ,则必须使用ПозжеонисталиизвестныподговорящейаббревиатуройМайкломФизерсом。 Этипринципыпомогаютписатьнадежный,гибкийкод。 Надежностьозначаетпростотуипонятностькода ,чтопозволяетлегковноситьвнегоизменения,упро Гибкостьпозволяетсминимальнымиусилиямимасштабироватьпроект ,则需将кодовуюбазубезвредвредвред。 固体 Чтожеобозначаетаббревиатура? S — 单一责任原则(SRP ) (SRP )或Принципединственнойответственности O — OCP ( 开放式封闭原则 ) L —ПринципподстановкиБ。 Лисков(里斯科夫替代原理LSP ) I — ISP ( 接口隔离原则,Interface Separation Principle,ISP ) D — 依赖倒置原理,DIP )( D) (Принципинверсиизависимостей) Опытномуразработчикумогутбытьочевиднывсепринципыдажепослебыстроговзгляданаихрасшифров。 Нооченьчастомногиеначинающиеразработчикинедоконцапонимают,почемуэтипринципытакважны。 Дляустраненияэтогопробелавзнанияхдавайтепройдемсяпокаждомуизних。 Принципединственнойответственности РобертМартинописывалеготак: Каждыйклассдолжениметьтолькооднупричинудляизменения Другимисловами,объектдолженнеститолькооднуответственность。 Егоинтерфейсиимплементациядолжныбытьнаправленытольконаэтуответственность。 Принципдолженсоблюдатьсявсигда:нетолькоприпроектированиикласса,ноиприегобагфиксе。 Оченьчастокласссоздается,следуяпринципу,нопотомвнегопопадаетвсё,чтотольковозможно。 […]

几乎可以使自己成功的应用

自从我7月开始Swift学习之旅以来,我发布到Apple App Store的大多数应用程序都是游戏。 实际上,它们都是非常基本的游戏。 我的发布时间表中的下两个应用程序也是游戏,尽管其中一个是具有多种测验类型的测验应用程序-稍后将进行更多介绍。 我的第一个非游戏应用程序于8月下旬启用,并且非常简单,几乎可以自行构建。 令人惊讶的是,IOS和Swift易于使用,尤其是由于大量易于使用且文档完善的库。 实际上,每个新版本使它们变得更容易。 在研究AVFoundation以便为基于声音的应用程序找到更好的方法和更多选择时,我遇到了AVSpeechSynthesizer。 基本上,它使您可以让电话语音读取已定义的字符串。 使用发话方法,texView和按钮,我可以允许用户编写内容并将其读取给他们。 为我说是出生的。 我添加了一些样式,一些预定义的快速短语和一个停止按钮。 我为应用程序添加了一些设计,并且可以开始使用了。 第一个版本几乎可以完成所有工作-让您编写文本并阅读,或者从四个预定义的文本字段之一中进行选择。 第二版将提供更多默认短语,让您创建自己的默认短语,甚至还可以阅读一些热门新闻。 在第二部分中,我将解释如何做到这一点,并提供一些示例代码,以便您可以自己完成。 您可以在Apple App Store上下载完成产品,或在GitHub上获取供自己使用的代码。

使用RxSwift时应避免的8个错误​​-第1部分

细节可能会有所不同,但是不管您的观察对象,观察者或订阅如何,基本含义都保持订阅的含义。 要发现的关键是,忽略参考周期管理器 (又称disposable ,可以使您摆脱自己破坏参考周期的可能性。 它是进入内存配置的门户药物,一旦无法使用,就再也没有回头路了。 如果使用_ =语法,则基本上可以说,释放observable observer和observer的唯一方法是完成可观察序列。 有时候这可能正是您想要的! 例如,如果您要调用Observable.just ,则不必确保打破周期,这并不重要。 单个元素被瞬时发出,随后是.completed事件。 但是,在许多情况下,您可能无法完全确定所讨论的可观察性的完成可能性: 您从另一个对象获得了Observable ,文档没有说明它是否完成, 您从另一个对象获得了Observable ,并且文档确实说明该对象已完成,但是在此过程中该对象的内部实现发生了一些变化,没有人记得要更新文档, Observable明显未完成(示例包括Variable , Observable.interval ,subject), 可观察的实现中存在错误,例如忘记在Observable.create闭包中发送.completed事件。 由于您几乎无法控制应用程序中的所有可观察对象,即使那样也有可能出错,因此经验法则是确保自己打破参考周期。 要么保留对disposable的引用,并在时间到时调用.dispose()方法,要么使用方便的助手(例如DisposeBag来帮您完成。 您还可以使用.takeUntil运算符提供一个单独的可观察到的循环中断。 选择哪种方式取决于您的具体情况,但请始终记住: 既然我们已经解决了所有问题,我觉得我欠您一点解释。 我上面绘制的心理模型很好,这是一种心理模型,因此并不严格正确。 当前的RxSwift实现(在撰写本文时版本3.x / 4.x)发生了一些复杂的事情。 要了解实际行为,让我们更深入地研究RxSwift内部。 在哪里实现subscribe方法? 毫无疑问,搜索的第一位将是ObservableType.swift文件。 它包含订阅方法的声明,作为ObservableType协议的一部分: func subscribe( _ observer: O ) -> Disposable where OE == E 什么实现了此协议? 基本上,所有各种类型的可观察物。 让我们集中讨论称为Observable的主要实现,因为它是RxSwift中定义的所有可观察对象(除了其中之一)的基类。 其subscribe方法版本简短而简单: public func subscribe( _ […]

Apple开发中的库,API,框架和SDK之间的关系。

有时我们会像类似元素一样谈论库,API和框架。 因此,我想简单地解释它们各自的含义以及它们之间的相互关系,以便您更好地理解它们。 此外,重要的是要知道SDK是Apple操作系统中的重要元素。 来吧,让我们说清楚! 图书馆 库是保存预编写代码的地方,可以调用这些代码来帮助您更快更轻松地完成工作。 该库基本上是一组元素,例如函数,类,常量,变量等,您可以在项目中使用它们来创建应用程序。 例子: Swift标准库解决了复杂的问题,并允许您编写高性能的可读代码。 这些库是用Swift编写程序的基本功能层,它们是为Swift设计的并以这种编程语言处理的一组数据类型和功能。 如果您用引号引起来的文本,例如“我喜欢制作原型”,那么Xcode将借助Swift标准库将其作为字符串进行处理。 如果输入: let a:Int = 10 ,则程序会将其解释为不带小数的整数。 例如: let sum = a + 1的结果为11。如果尝试使用let sum = a + 0.5 ,则会显示错误,因为编译器不允许常量和包含小数点后的数字。 但是,如果您编写: let b:Double = 10 ,程序将知道该数字可以有小数。 因此,如果您添加十进制值,例如: let add = b + 0.5 ,则结果为10.5。 API API(应用程序编程接口)是您的代码与一个或多个库之间的连接。 它与它所连接的库的版本有一定距离。 另外,API不包含实现细节。 例如,可能有多个库可以使用十进制Double或Float,并且每个库都有针对这些数字类型的完整实现。 尽管程序的API不会改变,但在这种情况下,会添加小数的API取决于您所使用的设备和操作系统,您将使用一个库或另一个库(对于macOS或iOs),具体取决于API。 例子: Apple Music API是音乐服务网络的一部分。 使用Apple […]

Apple Watch —并发症

Neste artigovocêirácompreender melhor o queéuma并发症,可随时用于实施uma。 Oéuma并发症? Apple Watch的复杂功能和可视化的相关信息,包括Apple Watch的相关应用程序,Apple Watch的相关信息,iOS应用程序的功能,功能和功能。 作为复杂并发症的重要信息,请参见家庭并发症的不同处理。 不同的布局,不同的形式,不同的表观,复杂的表壳,复杂的外观,以及各种形式。 由复杂性引起的动机和复杂性方面的问题,作为手表表盘的人可以将其保留下来。 苹果官方文件将其作为复杂性的家族成员: 圆 模块化小 模块化大 实用小 大型公用事业 超大 一位名叫圣玛利亚·拉多斯·阿尔冈斯的复杂事例,面目全非,Apple的文献资料 科莫funciona? Antes de tudo,重要的军刀并发症功能。 基本配置文件,可配置的uma并发症,最确定的时刻。 举例来说:想象一下,您将因复杂而复杂化,并因应自己的状态,并最终获得身份证明:没有任何权利,也没有权利。 时间轴的可视性和时间信息。 Ela pode ser utiliza para mostrar dados futuros ou dados passados。 时间轴的时间限制,时间轴的时间限制。 官方文件示例: 动手 Agora quevocêjásabe o queé和e que que ma并发症,迷走神经。 在马尼拉,您可以轻松实现以下目的: 在操作系统中使用“包括复杂性”的首字母缩略词,以了解其在以下方面的重要性: 可以使用ComplicationController.swift控件作为数据源和数据源的功能,在本地不等于时间轴的配置。 WatchKit扩展:在目标和目标之间进行选择: 一般情况下,将复杂配置作为运维,将“大型模块化”马尔代夫(ixsero apenas)称为“复杂”。 […]

在iOS中将渐变颜色快速应用于文本

渐变颜色很酷,尤其是将它们应用于文本时。 当然,您可以打开Photoshop或Sketch,对文本应用渐变,导出为png等。在以后需要更改字体,文本,间距等时,这是非常有限的。让我们学习如何使它们全部发生码! 通过下载游乐场来遵循:https://github.com/kgellci/GradientColorsInSwift 创建带有渐变颜色的视图。 在将渐变颜色应用于视图时,CAGradientLayer是您的朋友。 现在是时候添加标签并为文本遮罩渐变了! 您当然可以使用情节提要和自动布局来设置视图和标签。 如果视图更改大小,则必须相应地更新渐变图层的大小。 这足以让您自己开始探索渐变。 通过遮盖imageView或UIButtons标题标签来尝试上述示例。 您还可以浏览Shift的源代码:https://github.com/kgellci/Shift Shift可让您通过定时动画或设备运动快速创建渐变(倾斜设备可移动渐变)。

10小时内的Appdevcon 2018

3月16日,我到达阿姆斯特丹的PathéArena。 今天,标志性的电影院都与 Appdevcon 有关, Appdevcon 是应用程序开发人员(主要)为应用程序开发人员而举行的年度会议。 我进入,迅速拿起我的徽章,然后上楼梯去会议厅。 在那儿,我加入了越来越多的排队等候咖啡的开发人员。 在他们的背后,像CocoaheadsNL,荷兰Android用户组,Appsterdam和Egeniq(活动组织者)这样的赞助商正在共享美食。 拿到急需的黑咖啡和一瓶水后,我去了13号馆进行当天的第一次演讲。 演讲者:Ash Furrow ( Artsy ) 主题:通过建立更好的团队来构建更好的软件 一个非常鼓舞人心的演讲,与实际的发展无关。 相反,Ash专注于管理心理学以及如何为在那里的团队创造最佳的工作环境-从而构建更好的软件。 简而言之:创造一个每个人都感到安全,没有任何羞辱的空间,并有足够的空间进行公开讨论。 这将使人们指出错误,承认错误,最重要的是从错误中学习。 怎么样? 假设每个人都在尽自己最大的努力,预期并解决苦难,并始终表现出同情心。 此外,Ash推荐Radical Candor作为一本不错的书,并总结了协同作用的概念,因为“……团队是团队合作的总和”。 演讲者:保罗·哈德森( 用Swift破解 ) 主题:如何像专业人士一样进行调试 Pauls的话题全部是关于iOS和Swift的。 Paul从一个非常熟悉的示例开始,在代码中包括print()来检查问题,然后是另一个print()然后是另一个,然后是另一个……然后,您明白了。 Paul提供的解决方案很简单: 断点 。 他演示了如何使用它们在激活时自动打印东西或播放声音。 Paul解释说,而不是删除断点,而是检查BreakpointManager枚举以使其为有条件的。 假设您要调试登录流程。 将BreakpointManager.login设置为’true’,所有登录流程断点将被激活。 由于某些断点适用于所有应用程序,因此您甚至可以在团队中共享它们。 Paul还分享了其他有用的调试技术,该网站真棒,使他们对Assert,Precondition和FatalError有所了解,并为我们提供了许多新的见解。 咖啡时间(休闲时光! 在拍摄下一张咖啡因时,我遇到了前同事Dylan Drost,他刚刚在Cross Platform大厅完成了关于Flutter的演讲。 我请他分享精彩片段,他很高兴地做到了: Flutter的当前状态,例如Dart语言的自定义渲染引擎 Flutter当前缺少可用于生产的内容,例如视频播放和其他基本本机功能 Google大量投资Flutter和Android,因此实际上是在与自己竞争 Google的新操作系统Fuchsia可能会在Flutter被采纳为Android的替代品时发挥作用 我很快又给自己喝了杯咖啡,坐下来进行下一次演讲。 演讲者:Phil Nash( Jetbrains ) 主题:可选不是失败 Phil首先讨论了函数的域和共域,并继续探讨Swift的发展方式,在错误处理方面缺乏该语言,以及如何以及为何引入可选函数。 […]